//
//  MKUIListView.m
//  MKUI
//
//  Created by 苏尚进 on 2022/3/24.
//  Copyright © 2022 moon. All rights reserved.
//

#import "MKUIListView.h"
#import "UIView+MKUI.h"
#import "NSArray+MKUI_BinarySearch.h"
#import "NSObject+MKUI.h"
#import "CGGeometry+MKUI.h"
#import "UIImage+MKUI.h"
#import "NSArray+MKUI.h"
#import "UIScrollView+MKUI.h"
#import "UIColor+MKUI.h"
#import "MKUIPreCompile.h"

typedef enum : NSUInteger {
    MKUIListViewGroupCornerStyleNone,//没有圆角
    MKUIListViewGroupCornerStyleTop,//top添加圆角
    MKUIListViewGroupCornerStyleBottom,//bottom添加圆角
    MKUIListViewGroupCornerStyleAll,//top和bottom添加圆角
} MKUIListViewGroupCornerStyle;


NS_ASSUME_NONNULL_BEGIN
@class MKUIListViewAttributeContainerView;
@interface MKUIListViewAttribute : NSObject<NSCopying,MKComparatorProtocol>
@property(nonatomic,readonly) NSString *dictionaryKey;
@property(nonatomic,assign) CGRect frame;
@property(nonatomic,assign) CGFloat zIndex;
@property(nonatomic,strong,nullable) __kindof UIView *modelView;//attribute对应的原始视图
@property(nonatomic,strong,nullable) __kindof MKUIListViewAttributeContainerView *containerView;//attribute对应的原始视图的外层容器。可以为nil
@property(nonatomic,readonly,nullable) UIView *attributeView;//将要被添加显示的视图，默认为modelView
@property(nonatomic,readonly) NSIndexPath *sortedIndexPath;//用于排序

@property(nonatomic,assign) MKUIListViewStyle style;
@property(nonatomic,assign) MKUIListViewScrollDirection scrollDirection;
@property(nonatomic,readonly) MKCGAxis scrollAxis;

- (void)refreshAttribute;
- (void)applyAttribute;
- (NSComparisonResult)compare:(MKUIListViewAttribute *)other;

- (void)configAttributeWithListView:(MKUIListView *)listView;
@end
@interface MKUIListViewAttribute(SectionIndex)
@property(nonatomic,assign) NSInteger sectionIndex;
@property(nonatomic,assign) NSInteger itemIndex;
@end
NS_ASSUME_NONNULL_END

typedef enum{
    MKUIListViewHeadFootViewKindOfHead=0,    //头部
    MKUIListViewHeadFootViewKindOfFoot=1     //尾部
} MKUIListViewHeadFootViewKind;
NS_ASSUME_NONNULL_BEGIN
@interface MKUIListViewHeadFootViewAttribute : MKUIListViewAttribute
@property(nonatomic,assign) MKUIListViewHeadFootViewKind kind;
+ (NSString *)dictionaryKeyWithKind:(MKUIListViewHeadFootViewKind)kind;
- (id)initWithKind:(MKUIListViewHeadFootViewKind)kind view:(UIView *)modelView;
@end
NS_ASSUME_NONNULL_END

//分组背景视图属性
NS_ASSUME_NONNULL_BEGIN
@interface MKUIListViewSectionGroupBackgroundViewAttribute : MKUIListViewAttribute
@property(nonatomic,assign) NSInteger sectionIndex;

@property(nonatomic,strong,nullable) UIColor *groupBackgroundColor;
@property(nonatomic,assign) UIEdgeInsets groupInsets;
@property(nonatomic,assign) UIEdgeInsets groupInnertInsets;
@property(nonatomic,assign) CGFloat groupCornerRadius;
@property(nonatomic,assign,nullable) Class groupBackgroundViewClass;

+ (NSString *)dictionaryKeyWithSectionIndex:(NSInteger)sectionIndex;
- (id)initWithSectionIndex:(NSInteger)sectionIndex;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
@interface MKUIListViewSectionViewAttribute : MKUIListViewAttribute
@property(nonatomic,assign) NSInteger sectionIndex;
@property(nonatomic,assign) MKUIListViewSectionViewKind kind;
@property(nonatomic,assign) UIEdgeInsets groupInsets;
+ (NSString *)dictionaryKeyWithSectionIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind;
- (id)initWithSectionIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind view:(UIView *)modelView;
+ (NSIndexPath *)sortedIndexPathWithSectionIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
@class MKUIListViewCellAttributeContainerView;
@interface MKUIListViewCellAttribute : MKUIListViewAttribute
@property(nonatomic,strong) NSIndexPath *indexPath;
@property(nonatomic,assign) NSInteger itemIndex;
@property(nonatomic,assign) UIEdgeInsets groupInsets;
@property(nonatomic,assign) UIEdgeInsets groupInnerInsets;
@property(nonatomic,assign) CGFloat groupCornerRadius;
@property(nonatomic,assign) MKUIListViewGroupCornerStyle groupCornerStyle;

@property(nonatomic,assign) MKUIListViewCellSeparatorStyle separatorStyle;
@property(nonatomic,assign,nullable) Class separatorViewClass;
@property(nonatomic,strong,nullable) UIColor *separatorColor;
@property(nonatomic,strong,nullable) UIColor *separatorBackgroundColor;
@property(nonatomic,assign) CGFloat separatorSize;
@property(nonatomic,assign) UIEdgeInsets separatorInsets;
@property(nonatomic,assign) BOOL hasSeparator;//是否展示分隔线

- (void)configSeparatorView:(UIView *)separatorView;
- (nullable UIView *)createSeparatorView;

@property(nonatomic,readonly,nullable) MKUIListViewCellAttributeContainerView *cellContainerView;
+ (NSString *)dictionaryKeyWithIndexPath:(NSIndexPath *)indexPath;
- (id)initWithIndexPath:(NSIndexPath *)indexPath view:(UIView *)view;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
typedef enum : NSUInteger {
    _MKUIListViewAttributeCollectionTypeOfListViewHeadFoot,
    _MKUIListViewAttributeCollectionTypeOfListViewSection,
} _MKUIListViewAttributeCollectionType;
@interface _MKUIListViewAttributeCollection : NSObject
@property(nonatomic,strong) NSMutableArray<MKUIListViewAttribute *> *attributes;
@property(nonatomic,assign) _MKUIListViewAttributeCollectionType type;
@property(nonatomic,assign) MKUIListViewHeadFootViewKind headFootViewKind;//表头、表尾才有的值
@property(nonatomic,assign) NSInteger sectionIndex;//分组类型才有的值
+ (NSArray<_MKUIListViewAttributeCollection *> *) attributeCollectionsWithAttributes:(NSArray<MKUIListViewAttribute *> *)attributes;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
@interface MKUIListViewSectionAttributeModel : NSObject
@property(nonatomic,assign) CGRect frame;
@property(nonatomic,assign) NSInteger sectionIndex;
@property(nonatomic,assign) NSInteger numberOfItems;

@property(nonatomic,assign,nullable) Class groupBackgroundViewClass;
@property(nonatomic,strong,nullable) UIColor *groupBackgroundColor;
@property(nonatomic,strong,nullable) NSValue *groupInsetsValue;
@property(nonatomic,strong,nullable) NSNumber *groupCornerRadiusNumber;
@property(nonatomic,strong,nullable) NSValue *groupInnerInsetsValue;
@property(nonatomic,strong,nullable) NSNumber *cellInteritemSpacingNumber;

@property(nonatomic,strong,nullable) NSNumber *separatorStyleNumber;//分隔线样式
@property(nonatomic,strong,nullable) UIColor *separatorColor;//颜色
@property(nonatomic,strong,nullable) UIColor *separatorBackgroundColor;//背景颜色
@property(nonatomic,strong,nullable) NSNumber *separatorSizeNumber;//线宽
@property(nonatomic,strong,nullable) NSValue *separatorInsetsValue;//边距
@property(nonatomic,assign,nullable) Class separatorViewClass;//自定义展示类
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
@interface MKUIListViewAttributeContainerView()
@property(nonatomic,strong) UIView *contentView;//容器
@property(nonatomic,strong,nullable) UIView *attributeView;
@property(nonatomic,assign) MKUIListViewScrollDirection scrollDirection;
@property(nonatomic,assign) MKUIListViewStyle style;
- (id)initWithAttributeView:(nullable UIView *)attributeView;
- (void)customLayoutSubviews;
- (void)applyAttribute:(__kindof MKUIListViewAttribute *)attr;
- (UIEdgeInsets)safeAreaInsetsWithGroupInsets:(UIEdgeInsets)groupInsets;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
@interface MKUIListViewSectionGroupBackgroundAttributeContainerView : MKUIListViewAttributeContainerView
@property(nonatomic,strong,nullable) UIView *customBackgroundView;
@property(nonatomic,assign) UIEdgeInsets groupInsets;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN

@interface MKUIListViewCellAttributeContainerView : MKUIListViewAttributeContainerView
@property(nonatomic,strong,nullable) UIView *separatorView;
@property(nonatomic,assign) CGFloat groupCornerRadius;//MKUIListViewStyleGrouped样式时的分组容器的圆角值，默认为5
@property(nonatomic,assign) MKUIListViewGroupCornerStyle groupCornerStyle;
@property(nonatomic,assign) UIEdgeInsets groupInsets;
@property(nonatomic,assign) UIEdgeInsets groupInnerInsets;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
@interface MKUIListViewCellAttributeContainerView()
- (void)customLayoutSubviews;
@end
NS_ASSUME_NONNULL_END

#pragma mark -------------------------------
@implementation MKUIListViewAttribute
- (NSString *)description{
    return [NSString stringWithFormat:@"(%@,%p,sortedIndexPath:%@,frame:%@,modelView:%@)",NSStringFromClass(self.class),self,self.sortedIndexPath,NSStringFromCGRect(self.frame),self.modelView];
}
- (id)copyWithZone:(NSZone *)zone{
    MKUIListViewAttribute *obj = [[self.class alloc] init];
    obj.frame = self.frame;
    obj.zIndex = self.zIndex;
    obj.modelView = self.modelView;
    obj.containerView = self.containerView;
    obj.scrollDirection = self.scrollDirection;
    return obj;
}
- (UIView *)attributeView{
    return self.containerView?:self.modelView;
}
- (void)refreshAttribute{
    [self.attributeView setNeedsLayout];
    [self.modelView setNeedsLayout];
    [self.attributeView layoutIfNeeded];
    [self.modelView layoutIfNeeded];
}
- (void)applyAttribute{
    self.attributeView.mk_frameSafety = self.frame;
    self.attributeView.layer.zPosition = self.zIndex;
    
    MKUIListViewSectionGroupBackgroundAttributeContainerView *containerView = self.containerView;
    [containerView applyAttribute:self];
}
- (MKCGAxis)scrollAxis{
    MKCGAxis X = self.scrollDirection==UICollectionViewScrollDirectionHorizontal?MKCGAxisX:MKCGAxisY;
    return X;
}
- (NSString *)dictionaryKey{
    return self.mk_objectAddress;
}
- (void)setSectionIndex:(NSInteger)sectionIndex{
}
- (NSInteger)sectionIndex{
    return NSNotFound;
}
- (void)setItemIndex:(NSInteger)itemIndex{
    
}
- (NSInteger)itemIndex{
    return NSNotFound;
}
- (NSIndexPath *)sortedIndexPath{
    return [NSIndexPath indexPathForItem:0 inSection:0];
}
- (NSComparisonResult)compare:(MKUIListViewAttribute *)other{
    return [self.sortedIndexPath compare:other.sortedIndexPath];
}
- (NSComparisonResult)mk_compare:(__kindof id<MKComparatorProtocol>)other{
    return [self compare:other];
}
- (void)configAttributeWithListView:(MKUIListView *)listView{
    self.style = listView.style;
    self.scrollDirection = listView.scrollDirection;
}
@end


@implementation MKUIListViewHeadFootViewAttribute
- (id)initWithKind:(MKUIListViewHeadFootViewKind)kind view:(UIView *)modelView{
    if (self=[self init]) {
        self.kind = kind;
        self.modelView = modelView;
        self.containerView = [[MKUIListViewAttributeContainerView alloc] initWithAttributeView:self.modelView];
    }
    return self;
}
- (id)copyWithZone:(NSZone *)zone{
    MKUIListViewHeadFootViewAttribute *obj = [super copyWithZone:zone];
    obj.kind = self.kind;
    return obj;
}
+ (NSString *)dictionaryKeyWithKind:(MKUIListViewHeadFootViewKind)kind{
    return [NSString stringWithFormat:@"headfoot-%@",@(kind)];
}
- (NSString *)dictionaryKey{
    return [self.class dictionaryKeyWithKind:self.kind];
}
- (NSInteger)sectionIndex{
    return self.kind==MKUIListViewHeadFootViewKindOfHead?NSIntegerMin:NSIntegerMax;
}
- (NSIndexPath *)sortedIndexPath{
    NSUInteger indexes[] = {self.kind*999999};
    return [NSIndexPath indexPathWithIndexes:indexes length:1];
}
- (NSString *)description{
    return [NSString stringWithFormat:@"(%@,%p,kind:%@,frame:%@,modelView:%@)",NSStringFromClass(self.class),self,self.kind==MKUIListViewHeadFootViewKindOfHead?@"ListHead":@"ListFoot",NSStringFromCGRect(self.frame),self.modelView];
}
@end


@implementation MKUIListViewSectionGroupBackgroundViewAttribute
- (nonnull id)initWithSectionIndex:(NSInteger)sectionIndex {
    if(self=[self init]){
        self.sectionIndex = sectionIndex;
        self.containerView = [[MKUIListViewSectionGroupBackgroundAttributeContainerView alloc] initWithAttributeView:nil];
    }
    return self;
}
- (id)copyWithZone:(NSZone *)zone{
    MKUIListViewSectionGroupBackgroundViewAttribute *obj = [super copyWithZone:zone];
    obj.sectionIndex = self.sectionIndex;
    return obj;
}
+ (nonnull NSString *)dictionaryKeyWithSectionIndex:(NSInteger)sectionIndex {
    return [NSString stringWithFormat:@"section-background-%@",@(sectionIndex)];
}
- (NSString *)dictionaryKey{
    return [self.class dictionaryKeyWithSectionIndex:self.sectionIndex];
}
- (NSIndexPath *)sortedIndexPath{
    NSUInteger indexes[] = {1,self.sectionIndex};
    return [NSIndexPath indexPathWithIndexes:indexes length:2];
}
- (NSString *)description{
    return [NSString stringWithFormat:@"(%@,%p,section:%@,frame:%@,modelView:%@)",NSStringFromClass(self.class),self,@(self.sectionIndex),NSStringFromCGRect(self.frame),self.modelView];
}
- (void)configAttributeWithListView:(MKUIListView *)listView{
    [super configAttributeWithListView:listView];
    NSInteger sectionIndex = self.sectionIndex;
    self.groupInsets = [listView groupInsetsForSection:sectionIndex];
    self.groupInnertInsets = [listView groupInnerInsetsForSection:sectionIndex];
    self.groupCornerRadius = [listView groupCornerRadiusForSection:sectionIndex];
    self.groupBackgroundColor = [listView groupBackgroundColorForSection:sectionIndex];
    self.groupBackgroundViewClass = [listView groupBackgroundViewClassForSetion:sectionIndex];
}
@end

@implementation MKUIListViewSectionViewAttribute
- (id)initWithSectionIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind view:(UIView *)modelView{
    if (self=[super init]) {
        self.sectionIndex = sectionIndex;
        self.kind = kind;
        self.modelView = modelView;
        self.containerView = [[MKUIListViewAttributeContainerView alloc] initWithAttributeView:self.modelView];
    }
    return self;
}
- (id)copyWithZone:(NSZone *)zone{
    MKUIListViewSectionViewAttribute *obj = [super copyWithZone:zone];
    obj.sectionIndex = self.sectionIndex;
    obj.kind = self.kind;
    return obj;
}
+ (NSString *)dictionaryKeyWithSectionIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind{
    return [NSString stringWithFormat:@"section-%@-%@",@(sectionIndex),@(kind)];
}
- (NSString *)dictionaryKey{
    return [self.class dictionaryKeyWithSectionIndex:self.sectionIndex kind:self.kind];
}
- (NSIndexPath *)sortedIndexPath{
    return [self.class sortedIndexPathWithSectionIndex:self.sectionIndex kind:self.kind];
}
+ (NSIndexPath *)sortedIndexPathWithSectionIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind{
    NSUInteger indexes[] = {1,sectionIndex,kind*999999,sectionIndex};
    return [NSIndexPath indexPathWithIndexes:indexes length:4];
}
- (NSString *)description{
    return [NSString stringWithFormat:@"(%@,%p,section:%@,kind:%@,frame:%@,modelView:%@)",NSStringFromClass(self.class),self,@(self.sectionIndex),self.kind==MKUIListViewSectionViewKindOfHead?@"SectionHead":@"SectionFoot",NSStringFromCGRect(self.frame),self.modelView];
}
- (void)configAttributeWithListView:(MKUIListView *)listView{
    [super configAttributeWithListView:listView];
    NSInteger sectionIndex = self.sectionIndex;
    self.groupInsets = [listView groupInsetsForSection:sectionIndex];
}
@end

@implementation MKUIListViewCellAttribute
- (id)initWithIndexPath:(NSIndexPath *)indexPath view:(UIView *)view{
    if (self=[super init]) {
        self.modelView = view;
        self.containerView = [[MKUIListViewCellAttributeContainerView alloc] initWithAttributeView:self.modelView];
        self.indexPath = indexPath;
    }
    return self;
}
- (id)copyWithZone:(NSZone *)zone{
    MKUIListViewCellAttribute *obj = [[self.class alloc] init];
    obj.indexPath = self.indexPath;
    return obj;
}
- (MKUIListViewCellAttributeContainerView *)cellContainerView{
    return (MKUIListViewCellAttributeContainerView *)self.containerView;
}
+ (NSString *)dictionaryKeyWithIndexPath:(NSIndexPath *)indexPath{
    return [NSString stringWithFormat:@"cell-%@-%@",@(indexPath.section),@(indexPath.item)];
}
- (NSString *)dictionaryKey{
    return [self.class dictionaryKeyWithIndexPath:self.indexPath];
}
- (void)setSectionIndex:(NSInteger)sectionIndex{
    self.indexPath = [NSIndexPath indexPathForItem:self.indexPath.item inSection:sectionIndex];
}
- (NSInteger)sectionIndex{
    return self.indexPath.section;
}
- (NSInteger)itemIndex{
    return self.indexPath.item;
}
- (void)setItemIndex:(NSInteger)itemIndex{
    self.indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:self.sectionIndex];
}
- (NSIndexPath *)sortedIndexPath{
    NSInteger row = self.indexPath.row;
    NSUInteger indexes[] = {1,self.sectionIndex,1,row};
    return [NSIndexPath indexPathWithIndexes:indexes length:4];
}
- (NSString *)description{
    return [NSString stringWithFormat:@"(%@,%p,cellIndexPath:%@,frame:%@,modelView:%@)",NSStringFromClass(self.class),self,[NSString stringWithFormat:@"%ld-%ld",self.indexPath.section,self.indexPath.item],NSStringFromCGRect(self.frame),self.modelView];
}
- (void)configAttributeWithListView:(MKUIListView *)listView{
    [super configAttributeWithListView:listView];
    NSInteger sectionIndex = self.sectionIndex;
    self.groupInsets = [listView groupInsetsForSection:sectionIndex];
    self.groupInnerInsets = [listView groupInnerInsetsForSection:sectionIndex];
    self.groupCornerRadius = [listView groupCornerRadiusForSection:sectionIndex];
    
    if(listView.style==MKUIListViewStyleInsetGrouped){
        NSInteger sectionIndex = self.sectionIndex;
        NSInteger numberOfCells = [listView numberOfItemsInSection:sectionIndex];
        if(self.indexPath.item==0 && numberOfCells==1){
            self.groupCornerStyle = MKUIListViewGroupCornerStyleAll;
        }else if(self.indexPath.item==0 && numberOfCells>1){
            self.groupCornerStyle = MKUIListViewGroupCornerStyleTop;
        }else if(self.indexPath.item==numberOfCells-1 && numberOfCells>1){
            self.groupCornerStyle = MKUIListViewGroupCornerStyleBottom;
        }else{
            self.groupCornerStyle = MKUIListViewGroupCornerStyleNone;
        }
    }else{
        self.groupCornerStyle = MKUIListViewGroupCornerStyleNone;
    }
    [self configAttributeSeparatorWithListView:listView];
}
- (void)configAttributeSeparatorWithListView:(MKUIListView *)listView{
    NSInteger sectionIndex = self.sectionIndex;
    self.separatorStyle = [listView separatorStyleForSection:sectionIndex];
    if(self.separatorStyle!=MKUIListViewCellSeparatorStyleNone){
        NSInteger numberOfCells = [listView numberOfItemsInSection:sectionIndex];
        self.hasSeparator = self.indexPath.item!=numberOfCells-1;
    }else{
        self.hasSeparator = NO;
    }
    if(self.hasSeparator){
        self.separatorViewClass = [listView separatorViewClassForSection:sectionIndex]?:MKUIListViewSeparatorView.class;
        if(self.separatorViewClass==MKUIListViewSeparatorView.class||[self.separatorViewClass isSubclassOfClass:MKUIListViewSeparatorView.class]){
            self.separatorColor = [listView separatorColorForSection:sectionIndex];
            self.separatorBackgroundColor = [listView separatorBackgroundColorForSection:sectionIndex];
            self.separatorSize = [listView separatorSizeForSection:sectionIndex];
            self.separatorInsets = [listView separatorInsetsForSection:sectionIndex];
        }
    }
}
- (void)configSeparatorView:(UIView *)separatorView{
    if(!separatorView||![separatorView isKindOfClass:MKUIListViewSeparatorView.class])return;
    MKUIListViewSeparatorView *v = (MKUIListViewSeparatorView *)separatorView;
    v.scrollDirection = self.scrollDirection;
    v.separatorColor = self.separatorColor;
    v.backgroundColor = self.separatorBackgroundColor;
    v.separatorSize = self.separatorSize;
    v.contentInsts = self.separatorInsets;
}
- (UIView *)createSeparatorView{
    if(!self.hasSeparator)return nil;
    UIView *separatorView = [[self.separatorViewClass alloc] init];
    [self configSeparatorView:separatorView];
    return separatorView;
}
@end

@implementation _MKUIListViewAttributeCollection
- (id)init{
    if(self=[super init]){
        self.attributes = [[NSMutableArray alloc] init];
    }
    return self;
}
+ (NSArray<_MKUIListViewAttributeCollection *> *) attributeCollectionsWithAttributes:(NSArray<MKUIListViewAttribute *> *)attributes{
    NSMutableArray<_MKUIListViewAttributeCollection *> *attrCollections = [[NSMutableArray alloc] init];
    _MKUIListViewAttributeCollection *currentCollection = nil;
    for(int i=0;i<attributes.count;i++){
        __kindof MKUIListViewAttribute *attr = attributes[i];
        NSInteger sectionIndex = attr.sectionIndex;
        if([attr isKindOfClass:MKUIListViewHeadFootViewAttribute.class]){
            MKUIListViewHeadFootViewAttribute *headFootAttr = attr;
            if(!currentCollection||currentCollection.type!=_MKUIListViewAttributeCollectionTypeOfListViewHeadFoot||currentCollection.headFootViewKind!=headFootAttr.kind){
                currentCollection = [[_MKUIListViewAttributeCollection alloc] init];
                currentCollection.sectionIndex = sectionIndex;
                currentCollection.type = _MKUIListViewAttributeCollectionTypeOfListViewHeadFoot;
                currentCollection.headFootViewKind = headFootAttr.kind;
                [attrCollections addObject:currentCollection];
            }
            [currentCollection.attributes addObject:attr];
        }else{
            if(sectionIndex==NSNotFound)continue;
            if(!currentCollection||currentCollection.type!=_MKUIListViewAttributeCollectionTypeOfListViewSection||currentCollection.sectionIndex!=sectionIndex){
                currentCollection = [[_MKUIListViewAttributeCollection alloc] init];
                currentCollection.sectionIndex = sectionIndex;
                currentCollection.type = _MKUIListViewAttributeCollectionTypeOfListViewSection;
                [attrCollections addObject:currentCollection];
            }
            [currentCollection.attributes addObject:attr];
        }
    }
    return attrCollections;
}
@end

@implementation MKUIListViewSectionAttributeModel
- (id)init{
    if (self=[super init]) {
    }
    return self;
}
@end

typedef enum : NSUInteger {
    MKUIListViewPerformTypeAdd,//添加视图
    MKUIListViewPerformTypeRemove,//删除视图
    MKUIListViewPerformTypeUpdate,//修改视图属性:frame.origin，zIndex
    MKUIListViewPerformTypeReload,//重装加载视图，此时视图的size，view可能发生了变更
} MKUIListViewPerformType;
@interface MKUIListViewPerformOperation : NSObject
@property(nonatomic,strong) __kindof MKUIListViewAttribute *attribute;
@property(nonatomic,assign) MKUIListViewPerformType type;
@property(nonatomic,assign) MKUIListViewItemAnimation animation;
@property(nonatomic,strong,nullable) UIImage *attributeShotsImage;

- (id)initWithAttribute:(MKUIListViewAttribute *)attribute type:(MKUIListViewPerformType)type animation:(MKUIListViewItemAnimation)animation;
@end
@implementation MKUIListViewPerformOperation
- (id)initWithAttribute:(MKUIListViewAttribute *)attribute type:(MKUIListViewPerformType)type animation:(MKUIListViewItemAnimation)animation{
    if (self=[self init]) {
        self.attribute = attribute;
        self.type = type;
        self.animation = animation;
        if(type==MKUIListViewPerformTypeReload){
//            self.attributeShotsImage = attribute.attributeView.mk_screenshotsImage;
        }
    }
    return self;
}
@end

@interface MKUIListViewSeparatorView()
@end
@implementation MKUIListViewSeparatorView
- (id)initWithFrame:(CGRect)frame{
    if (self=[super initWithFrame:frame]) {
        self.lineView = [[UIView alloc] init];
        [self addSubview:self.lineView];
    }
    return self;
}
- (void)setContentInsts:(UIEdgeInsets)contentInsts{
    if(!UIEdgeInsetsEqualToEdgeInsets(_contentInsts, contentInsts)){
        _contentInsts = contentInsts;
        [self setNeedsLayout];
    }
}
- (void)setSeparatorColor:(UIColor *)separatorColor{
    self.lineView.backgroundColor = separatorColor;
}
- (UIColor *)separatorColor{
    return self.lineView.backgroundColor;
}
- (void)layoutSubviews{
    [super layoutSubviews];
    MKCGAxis Y = self.scrollAxis;
    CGRect bounds = self.bounds;
    CGRect f1 = bounds;
    
    //只使用与滚动方向垂直的分量
    UIEdgeInsets insets = self.contentInsts;
    MKUIEdgeInsetsSetEdge(&insets, Y, MKUIEdgeInsetsMin, 0);
    MKUIEdgeInsetsSetEdge(&insets, Y, MKUIEdgeInsetsMax, 0);
    f1 = UIEdgeInsetsInsetRect(bounds, insets);
    
    UIEdgeInsets safeArea = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        safeArea = self.safeAreaInsets;
    }
    MKUIEdgeInsetsSetEdge(&safeArea, Y, MKUIEdgeInsetsMin, 0);
    MKUIEdgeInsetsSetEdge(&safeArea, Y, MKUIEdgeInsetsMax, 0);
    f1 = UIEdgeInsetsInsetRect(f1, safeArea);
    
    self.lineView.frame = f1;
}
- (MKCGAxis)scrollAxis{
    MKCGAxis Y = self.scrollDirection==UICollectionViewScrollDirectionHorizontal?MKCGAxisX:MKCGAxisY;
    return Y;
}
- (CGSize)sizeThatFits:(CGSize)size{
    CGSize fitSit = size;
    MKCGAxis Y = self.scrollAxis;
    MKCGSizeSetLength(&fitSit, Y, self.separatorSize);
    return fitSit;
}
@end

@implementation MKUIListViewAttributeContainerView
- (id)initWithFrame:(CGRect)frame{
    if (self=[super initWithFrame:frame]) {
        self.contentView = [[UIView alloc] init];
        [self addSubview:self.contentView];
    }
    return self;
}
- (id)initWithAttributeView:(UIView *)attributeView{
    if (self=[self init]) {
        self.attributeView = attributeView;
    }
    return self;
}
- (void)customLayoutSubviews{
    CGRect bounds = self.bounds;
    {
        CGRect f1 = bounds;
        self.contentView.mk_frameSafety = f1;
    }
    {
        self.attributeView.mk_frameSafety = self.contentView.bounds;
    }
}
- (void)layoutSubviews{
    [super layoutSubviews];
    [self customLayoutSubviews];
}
- (CGSize)sizeThatFits:(CGSize)size{
    MKCGAxis Y = self.scrollAxis;
    CGSize fitSize = size;
    CGSize limitSize = size;
    MKCGSizeSetLength(&fitSize, Y, 0);
    if(self.attributeView){
        MKCGSizeAddLength(&fitSize, Y, MKCGSizeGetLength([self.attributeView sizeThatFits:limitSize], Y));
    }
    return fitSize;
}
- (void)setAttributeView:(UIView *)attributeView{
    if(_attributeView==attributeView) return;
    [_attributeView removeFromSuperview];
    _attributeView = attributeView;
    if(_attributeView){
        [self.contentView addSubview:_attributeView];
        [self setNeedsLayout];
    }
}
- (void)applyAttribute:(__kindof MKUIListViewAttribute *)attr{
    self.style = attr.style;
    self.scrollDirection = attr.scrollDirection;
}
- (MKCGAxis)scrollAxis{
    MKCGAxis X = self.scrollDirection==UICollectionViewScrollDirectionHorizontal?MKCGAxisX:MKCGAxisY;
    return X;
}
- (UIEdgeInsets)safeAreaInsetsWithGroupInsets:(UIEdgeInsets)groupInsets{
    if(self.style==MKUIListViewStylePlain) return groupInsets;
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    UIEdgeInsets insets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        insets = self.safeAreaInsets;
    }
    MKUIEdgeInsetsAddEdge(&insets, X, MKUIEdgeInsetsMin, MKUIEdgeInsetsGetEdge(groupInsets, X, MKUIEdgeInsetsMin));
    MKUIEdgeInsetsAddEdge(&insets, X, MKUIEdgeInsetsMax, MKUIEdgeInsetsGetEdge(groupInsets, X, MKUIEdgeInsetsMax));
    MKUIEdgeInsetsSetEdge(&insets, Y, MKUIEdgeInsetsMin, 0);
    MKUIEdgeInsetsSetEdge(&insets, Y, MKUIEdgeInsetsMax, 0);
    return insets;
}
@end

@implementation MKUIListViewSectionGroupBackgroundAttributeContainerView
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.contentView.clipsToBounds = YES;
    }
    return self;
}
- (UIEdgeInsets)safeAreaInsetsWithGroupInsets{
    if(self.style==MKUIListViewStylePlain)return UIEdgeInsetsZero;
    return [self safeAreaInsetsWithGroupInsets:self.groupInsets];
}
- (void)customLayoutSubviews{
    CGRect bounds = self.bounds;
    UIEdgeInsets insets = [self safeAreaInsetsWithGroupInsets];
    CGRect f1 = UIEdgeInsetsInsetRect(bounds, insets);
    self.contentView.frame = f1;
    self.customBackgroundView.frame = self.contentView.bounds;
}
- (void)applyAttribute:(__kindof MKUIListViewAttribute *)attr{
    [super applyAttribute:attr];
    MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = attr;
    self.groupInsets = sectionBgAttr.groupInsets;
    self.contentView.backgroundColor = sectionBgAttr.groupBackgroundColor;
    self.contentView.layer.cornerRadius = sectionBgAttr.style==MKUIListViewStyleInsetGrouped?sectionBgAttr.groupCornerRadius:0;
    [self reloadGroupBackgroundViewClass:sectionBgAttr.groupBackgroundViewClass];
    [self setNeedsLayout];
}
- (void)reloadGroupBackgroundViewClass:(Class)groupBackgroundViewClass{
    if(self.customBackgroundView){
        if(groupBackgroundViewClass!=nil&&[self.customBackgroundView isKindOfClass:groupBackgroundViewClass])return;
        [self.customBackgroundView removeFromSuperview];
        self.customBackgroundView = nil;
        if(groupBackgroundViewClass){
            self.customBackgroundView = [[groupBackgroundViewClass alloc] init];
            [self.contentView addSubview:self.customBackgroundView];
        }
    }else if(groupBackgroundViewClass){
        self.customBackgroundView = [[groupBackgroundViewClass alloc] init];
        [self.contentView addSubview:self.customBackgroundView];
    }
}
@end

@implementation MKUIListViewCellAttributeContainerView
- (UIEdgeInsets)safeAreaInsets{
    if(self.style==MKUIListViewStyleInsetGrouped){
        //group样式时，将safeArea应用到contentView等，然后设置contentView的safeArea设置为0
        return UIEdgeInsetsZero;
    }else{
        return [super safeAreaInsets];
    }
}
- (UIEdgeInsets)safeAreaInsetsWithGroupInsets{
    if(self.style==MKUIListViewStylePlain) return UIEdgeInsetsZero;
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    UIEdgeInsets insets = UIEdgeInsetsZero;
    MKUIEdgeInsetsSetEdge(&insets, X, MKUIEdgeInsetsMin, MKUIEdgeInsetsGetEdge(self.groupInsets, X, MKUIEdgeInsetsMin)+MKUIEdgeInsetsGetEdge(self.groupInnerInsets, X, MKUIEdgeInsetsMin));
    MKUIEdgeInsetsSetEdge(&insets, X, MKUIEdgeInsetsMax, MKUIEdgeInsetsGetEdge(self.groupInsets, X, MKUIEdgeInsetsMax)+MKUIEdgeInsetsGetEdge(self.groupInnerInsets, X, MKUIEdgeInsetsMax));
    return [self safeAreaInsetsWithGroupInsets:insets];
}
- (UIEdgeInsets)safeAreaInsetsWithGroupInsets:(UIEdgeInsets)groupInsets{
    if(self.style==MKUIListViewStylePlain) return groupInsets;
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    UIEdgeInsets insets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        insets = super.safeAreaInsets;//group样式时，将safeArea应用到contentView等，然后设置contentView的safeArea设置为0
    }
    MKUIEdgeInsetsAddEdge(&insets, X, MKUIEdgeInsetsMin, MKUIEdgeInsetsGetEdge(groupInsets, X, MKUIEdgeInsetsMin));
    MKUIEdgeInsetsAddEdge(&insets, X, MKUIEdgeInsetsMax, MKUIEdgeInsetsGetEdge(groupInsets, X, MKUIEdgeInsetsMax));
    MKUIEdgeInsetsSetEdge(&insets, Y, MKUIEdgeInsetsMin, 0);
    MKUIEdgeInsetsSetEdge(&insets, Y, MKUIEdgeInsetsMax, 0);
    return insets;
}
- (void)customLayoutSubviews{
    CGRect bounds = self.bounds;
    MKCGAxis Y = self.scrollAxis;
    UIEdgeInsets insets = [self safeAreaInsetsWithGroupInsets];
    if(self.separatorView){
        [self layoutSeparatorView:insets];
    }
    {
        //contentView不处理safeAreaInsets，交由内容处理
        CGRect f1 = UIEdgeInsetsInsetRect(bounds, insets);
        CGRect f2 = self.separatorView?self.separatorView.mk_frameSafety:CGRectZero;
        MKCGRectAddLength(&f1, Y, -MKCGRectGetLength(f2, Y));
        self.contentView.mk_frameSafety = f1;
    }
    {
        self.attributeView.mk_frameSafety = self.contentView.bounds;
    }
    [self reloadGroupStyle];
}
- (void)layoutSeparatorView:(UIEdgeInsets)insets{
    CGRect bounds = self.bounds;
    bounds = UIEdgeInsetsInsetRect(bounds, insets);
    
    //分隔线需要进行safeAreaInsets处理
    UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        safeAreaInsets = [self safeAreaInsets];
    }
    bounds = UIEdgeInsetsInsetRect(bounds, safeAreaInsets);
    
    MKCGAxis Y = self.scrollAxis;
    CGRect f1 = bounds;
    CGSize limitSize = bounds.size;
    CGSize fitSize = [self.separatorView sizeThatFits:limitSize];
    MKCGRectSetLength(&f1, Y, MKCGSizeGetLength(fitSize, Y));
    MKCGRectSetMaxEdgeToRect(&f1, Y, bounds, 0);
    self.separatorView.mk_frameSafety = f1;
}
- (void)applyAttribute:(__kindof MKUIListViewAttribute *)attr{
    [super applyAttribute:attr];
    MKUIListViewCellAttribute *cellAttr = attr;
    self.groupCornerRadius = cellAttr.groupCornerRadius;
    self.groupCornerStyle = cellAttr.groupCornerStyle;
    self.groupInsets = cellAttr.groupInsets;
    self.groupInnerInsets = cellAttr.groupInnerInsets;
    [self reloadSeparatorView:cellAttr];
}
- (void)reloadSeparatorView:(MKUIListViewCellAttribute *)cellAttr{
    if(cellAttr.hasSeparator){
        UIView *oldSeparatorView = self.separatorView;
        UIView *separatorView = nil;
        if(oldSeparatorView&&[oldSeparatorView isKindOfClass:cellAttr.separatorViewClass]){
            separatorView = oldSeparatorView;
            [cellAttr configSeparatorView:separatorView];
        }else{
            separatorView = [cellAttr createSeparatorView];
        }
        self.separatorView = separatorView;
    }else{
        self.separatorView = nil;
    }
}
- (void)reloadGroupStyle{
    if(self.style==MKUIListViewStylePlain){
        self.layer.mask = nil;
        return;
    }
    MKCGAxis Y = [self scrollAxis];
    CGFloat groupCornerRadius = self.groupCornerRadius;
    UIBezierPath *path = [[UIBezierPath alloc] init];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    CGRect f1 = self.contentView.mk_frameSafety;
    if(self.separatorView){
        CGRect f2 = self.separatorView.mk_frameSafety;
        MKCGRectAddLength(&f1, Y, MKCGRectGetLength(f2, Y));
    }
    switch (self.groupCornerStyle) {
        case MKUIListViewGroupCornerStyleTop:
            MKCGRectAddLength(&f1, Y, groupCornerRadius);
            [path appendPath:[UIBezierPath bezierPathWithRoundedRect:f1 cornerRadius:groupCornerRadius]];
            break;
        case MKUIListViewGroupCornerStyleBottom:
            MKCGRectAddLength(&f1, Y, groupCornerRadius);
            MKCGRectAddMin(&f1, Y, -groupCornerRadius);
            [path appendPath:[UIBezierPath bezierPathWithRoundedRect:f1 cornerRadius:groupCornerRadius]];
            break;
        case MKUIListViewGroupCornerStyleAll:
            [path appendPath:[UIBezierPath bezierPathWithRoundedRect:f1 cornerRadius:groupCornerRadius]];
            break;
        case MKUIListViewGroupCornerStyleNone:
            [path appendPath:[UIBezierPath bezierPathWithRect:f1]];
            break;
        default:
            maskLayer = nil;
            break;
    }
    maskLayer.path = path.CGPath;
    self.layer.mask = maskLayer;
}
- (void)setSeparatorView:(UIView *)separatorView{
    if(_separatorView==separatorView)return;
    [_separatorView removeFromSuperview];
    _separatorView = separatorView;
    if(_separatorView){
        [self addSubview:_separatorView];
        [self bringSubviewToFront:_separatorView];
        [self layoutSeparatorView:[self safeAreaInsetsWithGroupInsets]];
    }
}
@end


@interface MKUIListView(){
    BOOL _needReloadAll;
    BOOL _needPerformBatchUpdates;
}
@property(nonatomic,strong) UIView *contentView;
@property(nonatomic,strong) NSMutableArray<__kindof MKUIListViewAttribute *> *attributes;//所有要显示的视图属性,已按顺序排好,包含列表头尾部视图，分组的头尾部视图，单元格，分隔线
@property(nonatomic,strong) NSMutableArray<__kindof MKUIListViewSectionGroupBackgroundViewAttribute *> *sectionGroupBacgroundAttributes;//装饰

@property(nonatomic,strong) NSMutableDictionary<NSString *,__kindof MKUIListViewAttribute *> *attributeMap;///key=MKUIListViewAttribute.dictionaryKey,方便根据位置找到对应的视图属性
@property(nonatomic,strong) NSMutableDictionary<NSString *,__kindof MKUIListViewAttribute *> *attributeAddressMap;//key=view.mk_objectAddress
@property(nonatomic,strong) NSMutableArray<MKUIListViewSectionAttributeModel *> *sectionModels;//分组对象

@property(nonatomic,assign) BOOL performingBatchUpdates;//是否正在执行批量变更操作中
@property(nonatomic,strong) NSMutableDictionary<NSString *,MKUIListViewPerformOperation *> *performOperations;//列表头、尾、分组头、尾、单元格的变更操作。key为view.mk_objectAddress
@property(nonatomic,strong,nullable) MKUIListViewAttribute *attributeOfScrollTo;
@property(nonatomic,assign) MKUIListViewScrollPosition attributeOfScrollToPositon;
@property(nonatomic,strong) NSArray<MKUIListViewAttribute *> *cachedVisiableAttributes;//当前正在显示中的视图属性列表
@property(nonatomic,strong) NSIndexPath *touchingCellIndexPath;
@end

@implementation MKUIListView
- (instancetype)initWithFrame:(CGRect)frame style:(MKUIListViewStyle)style{
    if(self=[super initWithFrame:frame]){
        self.backgroundColor = UIColor.mk_listViewBackgroundColor;
        _groupBackgroundColor = UIColor.mk_listViewGroupBackgroundColor;
        
        _style = style;
        _groupInsets = UIEdgeInsetsMake(10, 10, 10, 10);
        _groupCornerRadius = 10;
        _groupInnerInsets = UIEdgeInsetsZero;
        self.scrollDirection = MKUIListViewScrollDirectionVertical;
        self.alwaysBounceVertical = YES;
        self.alwaysBounceHorizontal = NO;
        //
        self.attributes = [[NSMutableArray alloc] init];
        self.sectionGroupBacgroundAttributes = [[NSMutableArray alloc] init];
        self.attributeMap = [[NSMutableDictionary alloc] init];
        self.attributeAddressMap = [[NSMutableDictionary alloc] init];
        self.sectionModels = [[NSMutableArray alloc] init];
        
        self.performOperations = [[NSMutableDictionary alloc] init];
        //
        self.contentView = [[UIView alloc] initWithFrame:frame];
        _separatorColor = UIColor.mk_listViewSeparatorColor;
        _separatorSize = 1.0/[UIScreen mainScreen].scale;
        [self addSubview:self.contentView];
        
        _needReloadAll = YES;
    }
    return self;
}
- (id)initWithFrame:(CGRect)frame{
    return [self initWithFrame:frame style:(MKUIListViewStylePlain)];
}
- (void)setScrollDirection:(MKUIListViewScrollDirection)scrollDirection{
    if(_scrollDirection==scrollDirection)return;
    _scrollDirection = scrollDirection;
    if(_scrollDirection==MKUIListViewScrollDirectionVertical){
        self.alwaysBounceVertical = YES;
        self.alwaysBounceHorizontal = NO;
    }else{
        self.alwaysBounceVertical = NO;
        self.alwaysBounceHorizontal = YES;
    }
}
- (void)layoutSubviews{
    [super layoutSubviews];
    if(_needPerformBatchUpdates){
        _needPerformBatchUpdates = NO;
        BOOL animated = NO;
        NSArray<MKUIListViewPerformOperation *> *performOperations = self.performOperations.allValues;
        for(MKUIListViewPerformOperation *operation in performOperations){
            if(operation.animation!=MKUIListViewItemAnimationNone){
                animated = YES;
                break;
            }
        }
        [self _applyAttributeChangeWithAnimated:animated completion:^(BOOL finished) {
            if(self.attributeOfScrollTo){
                [self _scrollToAttribute:self.attributeOfScrollTo atScrollPosition:self.attributeOfScrollToPositon animated:NO completion:^(BOOL finished) {
                    self.attributeOfScrollTo = nil;
                    self.attributeOfScrollToPositon = MKUIListViewScrollPositionNone;
                }];
            }
        }];
    }
}
- (void)willTransitionToSizeChange{
    MKCGAxis Y = self.scrollAxis;
    CGPoint offset = self.contentOffset;
    NSArray<MKUIListViewAttribute *> *attrs = [self _attributesInRect:[self _realVisiableBounds]];
    UIEdgeInsets offsetRange = self.mk_contentOffsetOfRange;
    
    if(attrs.count){
        if(MKCGPointGetValue(offset, Y)<=MKUIEdgeInsetsGetEdge(offsetRange, Y, MKUIEdgeInsetsMin)){
            self.attributeOfScrollToPositon = MKUIListViewScrollPositionHead;
            self.attributeOfScrollTo = attrs.firstObject;
        }else if(MKCGPointGetValue(offset, Y)>=MKUIEdgeInsetsGetEdge(offsetRange, Y, MKUIEdgeInsetsMax)){
            self.attributeOfScrollToPositon = MKUIListViewScrollPositionFoot;
            self.attributeOfScrollTo = attrs.lastObject;
        }else{
            self.attributeOfScrollToPositon = MKUIListViewScrollPositionMiddle;
            CGPoint centerPoint = self.mk_centerPointOfContent;
            self.attributeOfScrollTo = [self _attributeNearestToPoint:centerPoint];
        }
    }
}
- (void)setFrame:(CGRect)frame{
    CGRect oldFrame = self.frame;
    CGRect newFrame = frame;
    BOOL frameChange = !CGSizeEqualToSize(oldFrame.size, newFrame.size);
    [super setFrame:frame];
    if(frameChange){
        [self _reloadDataWithAnimation:(MKUIListViewItemAnimationNone)];
    }
}
- (void)setContentOffset:(CGPoint)contentOffset{
    if(self.attributeOfScrollTo){
        [super setContentOffset:contentOffset];
        [self _reloadBackgroundView];
    }else if(CGPointEqualToPoint(self.contentOffset, contentOffset)){
        [super setContentOffset:contentOffset];
        [self _reloadBackgroundView];
    }else{
        NSArray<MKUIListViewAttribute *> *oldVisiableAttributes = self.cachedVisiableAttributes;
        [super setContentOffset:contentOffset];
        [self _reloadBackgroundView];
        NSArray<MKUIListViewAttribute *> *newVisiableAttributes = [self _visiableAttributes];
        NSArray<MKUIListViewAttribute *> *addVisiableAttributes = [newVisiableAttributes mk_removeSortedObjectsInArray:oldVisiableAttributes asc:YES];
        NSArray<MKUIListViewAttribute *> *deleteVisiableAttributes = [oldVisiableAttributes mk_removeSortedObjectsInArray:newVisiableAttributes asc:YES];
        for (MKUIListViewAttribute *attr in addVisiableAttributes) {
            [self _notifyAttributeViewWillDisplay:attr];
        }
        for (MKUIListViewAttribute *attr in deleteVisiableAttributes) {
            [self _notifyAttributeViewDidEndDisplaying:attr];
        }
        self.cachedVisiableAttributes = newVisiableAttributes;
    }
}
- (MKCGAxis)scrollAxis{
    MKCGAxis X = self.scrollDirection==UICollectionViewScrollDirectionHorizontal?MKCGAxisX:MKCGAxisY;
    return X;
}
- (NSInteger)numberOfSections{
    NSInteger sections = self.sectionModels.count;
    return sections;
}
- (NSInteger)numberOfItems{
    NSInteger rows = 0;
    for (MKUIListViewSectionAttributeModel *sectionAttr in self.sectionModels) {
        rows += sectionAttr.numberOfItems;
    }
    return rows;
}
- (NSUInteger)numberOfItemsInSection:(NSInteger)sectionIndex{
    NSInteger rows = [self _sectionAttributeModelAtIndex:sectionIndex].numberOfItems;
    return rows;
}
- (CGRect)rectForSection:(NSInteger)section{
    CGRect rect = CGRectNull;
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel){
        rect = sectionModel.frame;
    }
    return rect;
}
- (CGRect)rectForKind:(MKUIListViewSectionViewKind)kind inSection:(NSInteger)section{
    CGRect rect = CGRectNull;
    MKUIListViewSectionViewAttribute *attr = self.attributeMap[[MKUIListViewSectionViewAttribute dictionaryKeyWithSectionIndex:section kind:kind]];
    if(attr){
        rect = attr.frame;
    }
    return rect;
}
- (CGRect)rectForItemAtIndexPath:(NSIndexPath *)indexPath{
    CGRect rect = CGRectNull;
    MKUIListViewCellAttribute *attr = self.attributeMap[[MKUIListViewCellAttribute dictionaryKeyWithIndexPath:indexPath]];
    if(attr){
        rect = attr.frame;
    }
    return rect;
}
- (CGRect)rectForListHeaderView{
    return [self rectForListHeadFooterViewWithKind:(MKUIListViewHeadFootViewKindOfHead)];
}
- (CGRect)rectForListFooterView{
    return [self rectForListHeadFooterViewWithKind:(MKUIListViewHeadFootViewKindOfFoot)];
}
- (CGRect)rectForListHeadFooterViewWithKind:(MKUIListViewHeadFootViewKind)kind{
    CGRect rect = CGRectNull;
    MKUIListViewAttribute *attr = self.attributeMap[[MKUIListViewHeadFootViewAttribute dictionaryKeyWithKind:(kind)]];
    if(attr){
        rect = attr.frame;
    }
    return rect;
}
- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point{
    NSIndexPath *indexPath = nil;
    MKUIListViewAttribute *attr = [self _attributeAtPoint:point];
    if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        indexPath = cellAttr.indexPath;
    }
    return indexPath;
}
- (nullable UIView *)viewAtPoint:(CGPoint)point{
    MKUIListViewAttribute *attr = [self _attributeAtPoint:point];
    return attr.modelView;
}
- (nullable UIView *)viewThatNearestToPoint:(CGPoint)point{
    MKUIListViewAttribute *attr = [self _attributeNearestToPoint:point];
    return attr.modelView;
}
- (nullable NSIndexPath *)indexPathForCell:(UIView *)cell{
    MKUIListViewAttribute *attr = self.attributeAddressMap[cell.mk_objectAddress];
    if(![attr isKindOfClass:MKUIListViewCellAttribute.class]) return nil;
    return [(MKUIListViewCellAttribute *)attr indexPath];
}
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForView:(UIView *)view{
    if(!view){
        return nil;
    }
    return self.attributeAddressMap[view.mk_objectAddress].containerView;
}
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForListHeadView{
    return self.attributeMap[[MKUIListViewHeadFootViewAttribute dictionaryKeyWithKind:(MKUIListViewHeadFootViewKindOfHead)]].containerView;
}
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForListFootView{
    return self.attributeMap[[MKUIListViewHeadFootViewAttribute dictionaryKeyWithKind:(MKUIListViewHeadFootViewKindOfFoot)]].containerView;
}
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForSectionAtIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind{
    return self.attributeMap[[MKUIListViewSectionViewAttribute dictionaryKeyWithSectionIndex:sectionIndex kind:kind]].containerView;
}
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForItemAtIndexPath:(NSIndexPath *)indexPath{
    return [self _cellAttributeAtIndexPath:indexPath].containerView;
}
- (nullable NSArray<NSIndexPath *> *)indexPathsForItemsInRect:(CGRect)rect{
    return [[self _attributesInRect:rect] mk_map:^id _Nullable(MKUIListViewAttribute * _Nonnull attr) {
        if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
            MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
            return cellAttr.indexPath;
        }
        return nil;
    }];
}
- (nullable __kindof UIView *)cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    return [self _cellAttributeAtIndexPath:indexPath].modelView;
}
- (nullable NSArray<__kindof UIView *> *)cellsForItemsInSectionIndex:(NSInteger)sectionIndex{
    return [[self _attributesWithSectionIndex:sectionIndex] mk_map:^id _Nullable(MKUIListViewAttribute * _Nonnull obj) {
        if([obj isKindOfClass:MKUIListViewCellAttribute.class]){
            MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)obj;
            return cellAttr.modelView;
        }
        return nil;
    }];
}
- (nullable NSArray<__kindof UIView *> *)viewsAfterItemAtIndexPath:(NSIndexPath *)indexPath{
    return [[self _attributesAfter:[self _cellAttributeAtIndexPath:indexPath] contain:NO] mk_map:^id _Nullable(MKUIListViewAttribute * _Nonnull obj) {
        return obj.modelView;
    }];
}
- (NSArray<UIView *> *)visibleCells{
    return [[self _visiableAttributes] mk_map:^id _Nullable(MKUIListViewAttribute * _Nonnull obj) {
        if([obj isKindOfClass:MKUIListViewCellAttribute.class]){
            MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)obj;
            return cellAttr.modelView;
        }
        return nil;
    }];
}
- (NSArray<NSIndexPath *> *)indexPathsForVisibleItems{
    return [self indexPathsForItemsInRect:[self _realVisiableBounds]];
}
- (nullable UIView *)sectionViewForSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind{
    MKUIListViewSectionViewAttribute *attr = self.attributeMap[[MKUIListViewSectionViewAttribute dictionaryKeyWithSectionIndex:section kind:kind]];
    return attr.modelView;
}
- (NSInteger)indexForSectionView:(UIView *)sectionView kind:(MKUIListViewSectionViewKind *)kind{
    NSInteger index = NSNotFound;
    MKUIListViewSectionViewAttribute *attr = self.attributeAddressMap[sectionView.mk_objectAddress];
    if(attr){
        index = attr.sectionIndex;
        if(kind){
            *kind = attr.kind;
        }
    }
    return index;
}
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(MKUIListViewScrollPosition)scrollPosition animated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion{
    if(CGSizeEqualToSize(CGSizeZero, self.bounds.size)){
        if(completion){
            completion(YES);
        }
        return;
    }
    MKUIListViewCellAttribute *cellAttr = [self _cellAttributeAtIndexPath:indexPath];
    if(!cellAttr){
        if(completion){
            completion(YES);
        }
        return;
    }
    [self _scrollToAttribute:cellAttr atScrollPosition:scrollPosition animated:animated completion:completion];
}
- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates animated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion{
    self.performingBatchUpdates = YES;
    if(updates){
        updates();
    }
    [self _applyAttributeChangeWithAnimated:animated completion:^(BOOL finished) {
        self.performingBatchUpdates = NO;
        if(completion){
            completion(finished);
        }
    }];
}
- (void)scrollToView:(UIView *)view atScrollPosition:(MKUIListViewScrollPosition)scrollPosition animated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion{
    MKUIListViewAttribute *attr = self.attributeAddressMap[view.mk_objectAddress];
    [self _scrollToAttribute:attr atScrollPosition:scrollPosition animated:animated completion:completion];
}
- (void)insertSectionAtIndex:(NSInteger)sectionIndex{
    if(!(sectionIndex>=0&&sectionIndex<=self.sectionModels.count))return;
    MKUIListViewSectionAttributeModel *sectionModel = [[MKUIListViewSectionAttributeModel alloc] init];
    sectionModel.sectionIndex = sectionIndex;
    
    //修改sectionIndex后的index值
    NSArray<MKUIListViewAttribute *> *nextAttrs = [self _attributesAfterOrEqualSectionIndex:sectionIndex];
    for (MKUIListViewAttribute *attr in nextAttrs) {
        [self.attributeMap removeObjectForKey:attr.dictionaryKey];
        attr.sectionIndex++;
        self.attributeMap[attr.dictionaryKey] = attr;
    }
    
    [self.sectionModels insertObject:sectionModel atIndex:sectionIndex];
    for (NSInteger i=sectionIndex+1; i<self.sectionModels.count; i++) {
        MKUIListViewSectionAttributeModel *s = self.sectionModels[i];
        s.sectionIndex++;
    }
    
    //添加分组背景
    MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = [[MKUIListViewSectionGroupBackgroundViewAttribute alloc] initWithSectionIndex:sectionIndex];
    [self.sectionGroupBacgroundAttributes insertObject:sectionBgAttr atIndex:sectionIndex];
    self.attributeMap[sectionBgAttr.dictionaryKey] = sectionBgAttr;
    self.attributeAddressMap[sectionBgAttr.mk_objectAddress] = sectionBgAttr;
    [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:sectionBgAttr type:(MKUIListViewPerformTypeAdd) animation:MKUIListViewItemAnimationNone]];
    
    //更新后续分组的sectionIndex值
    NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *sectionBgAttrs = [self _sectionGroupBackgroundAttributesAfterSection:sectionIndex];
    for(MKUIListViewSectionGroupBackgroundViewAttribute *attr in sectionBgAttrs){
        [self.attributeMap removeObjectForKey:attr.dictionaryKey];
        attr.sectionIndex++;
        self.attributeMap[attr.dictionaryKey] = attr;
    }
}
- (void)addSection{
    [self insertSectionAtIndex:self.numberOfSections];
}
- (void)addSectionWithHeadView:(nullable UIView *)sectionHeadView footView:(nullable UIView *)sectionFootView{
    [self addSectionWithHeadView:sectionHeadView footView:sectionFootView withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)addSectionWithHeadView:(nullable UIView *)sectionHeadView footView:(nullable UIView *)sectionFootView withAnimation:(MKUIListViewItemAnimation)animation{
    NSInteger sectionIndex = self.numberOfSections;
    [self insertSectionAtIndex:sectionIndex];
    [self setSectionView:sectionHeadView atIndex:sectionIndex kind:(MKUIListViewSectionViewKindOfHead) withAnimation:animation];
    [self setSectionView:sectionFootView atIndex:sectionIndex kind:(MKUIListViewSectionViewKindOfFoot) withAnimation:animation];
}
- (void)setSectionView:(nullable UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind{
    [self setSectionView:sectionView atIndex:sectionIndex kind:kind withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)setSectionView:(nullable UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:sectionIndex];
    if(!sectionModel){
        if(sectionView && sectionIndex==self.sectionModels.count){//自动往末尾添加一个空白分组
            [self insertSectionAtIndex:sectionIndex];
        }else{
            return;
        }
    }
    MKUIListViewSectionViewAttribute *oldSectionAttr = self.attributeMap[[MKUIListViewSectionViewAttribute dictionaryKeyWithSectionIndex:sectionIndex kind:kind]];
    if(oldSectionAttr.modelView==sectionView){//没有变化
        return;
    }
    MKUIListViewSectionViewAttribute *sectionAttr;
    MKUIListViewPerformOperation *opertaion = [self _performOpertionForView:sectionView];
    if(opertaion){
        switch (opertaion.type) {
            case MKUIListViewPerformTypeAdd://重复添加，取消此次操作
            case MKUIListViewPerformTypeReload:
            case MKUIListViewPerformTypeUpdate:
                return;
                break;
            case MKUIListViewPerformTypeRemove://标记为删除，再次添加
                if(![opertaion.attribute isKindOfClass:MKUIListViewSectionViewAttribute.class])return;
                sectionAttr = (MKUIListViewSectionViewAttribute *)opertaion.attribute;
                sectionAttr.sectionIndex = sectionIndex;
                sectionAttr.kind = kind;
                break;
            default:
                break;
        }
    }
    
    [self _beforeUpdateAttributes];
    
    if(oldSectionAttr){
        [self _removeAttribute:oldSectionAttr withAnimation:animation];
    }
    if(sectionView){
        if(!sectionAttr) sectionAttr = [[MKUIListViewSectionViewAttribute alloc] initWithSectionIndex:sectionIndex kind:kind view:sectionView];
        [self _insertAttribute:sectionAttr withAnimation:animation];
    }
    
    [self _afterUpdateAttributes];
}
- (void)deleteSectionViewsAtIndex:(NSInteger)sectionIndex{
    [self deleteSectionViewsAtIndex:sectionIndex withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)deleteSectionViewsAtIndex:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation{
    if(!(sectionIndex>=0&&sectionIndex<self.sectionModels.count))return;
    NSArray<MKUIListViewAttribute *> *deleteAttrs = [self _attributesWithSectionIndex:sectionIndex];
    
    [self _beforeUpdateAttributes];
    [self _removeAttributes:deleteAttrs withAnimation:animation];
    [self _afterUpdateAttributes];
}
- (void)deleteSectionAtIndex:(NSInteger)sectionIndex{
    [self deleteSectionAtIndex:sectionIndex withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)deleteSectionAtIndex:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation{
    if(!(sectionIndex>=0&&sectionIndex<self.sectionModels.count))return;
    NSArray<MKUIListViewAttribute *> *nextAttrs = [self _attributesAfterSectionIndex:sectionIndex];
    NSArray<MKUIListViewAttribute *> *deleteAttrs = [self _attributesWithSectionIndex:sectionIndex];
    
    [self _beforeUpdateAttributes];
    
    [self.sectionModels removeObjectAtIndex:sectionIndex];
    for (MKUIListViewAttribute *attr in deleteAttrs) {
        [self.attributes removeObject:attr];
        [self.attributeMap removeObjectForKey:attr.dictionaryKey];
        [self.attributeAddressMap removeObjectForKey:attr.mk_objectAddress];
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeRemove) animation:(animation)]];
    }
    
    for (MKUIListViewAttribute *attr in nextAttrs) {
        [self.attributeMap removeObjectForKey:attr.dictionaryKey];
        attr.sectionIndex--;
        self.attributeMap[attr.dictionaryKey] = attr;
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeUpdate) animation:(animation)]];
    }
    
    //删除分组背景
    MKUIListViewSectionGroupBackgroundViewAttribute *deleteSectionBgAttr = [self _sectionGroupBackgroundAttributesAtSection:sectionIndex];
    NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *sectionBgAttrs = [self _sectionGroupBackgroundAttributesAfterSection:sectionIndex];
    [self.sectionGroupBacgroundAttributes removeObjectAtIndex:sectionIndex];
    [self.attributeMap removeObjectForKey:deleteSectionBgAttr.dictionaryKey];
    [self.attributeAddressMap removeObjectForKey:deleteSectionBgAttr.mk_objectAddress];
    [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:deleteSectionBgAttr type:(MKUIListViewPerformTypeRemove) animation:(animation)]];
    
    //update分组背景
    for(MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr in sectionBgAttrs){
        [self.attributeMap removeObjectForKey:sectionBgAttr.dictionaryKey];
        sectionBgAttr.sectionIndex--;
        self.attributeMap[sectionBgAttr.dictionaryKey] = sectionBgAttr;
    }
    [self _updateSectionGroupBackgroundAttributes:sectionBgAttrs withAnimation:animation];
    
    [self _afterUpdateAttributes];
}
- (void)_reloadSectionGroupBackgroundAttribute:(MKUIListViewSectionGroupBackgroundViewAttribute *)sectionBgAttr withAnimation:(MKUIListViewItemAnimation)animation{
    if(!sectionBgAttr)return;
    [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:sectionBgAttr type:(MKUIListViewPerformTypeReload) animation:(animation)]];
}
- (void)_reloadSectionGroupBackgroundAttributes:(NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *)sectionBgAttrs withAnimation:(MKUIListViewItemAnimation)animation{
    //update分组背景
    for(MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr in sectionBgAttrs){
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:sectionBgAttr type:(MKUIListViewPerformTypeReload) animation:(animation)]];
    }
}
- (void)_updateSectionGroupBackgroundAttributes:(NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *)sectionBgAttrs withAnimation:(MKUIListViewItemAnimation)animation{
    //update分组背景
    for(MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr in sectionBgAttrs){
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:sectionBgAttr type:(MKUIListViewPerformTypeUpdate) animation:(animation)]];
    }
}
- (void)deleteSectionView:(UIView *)sectionView{
    [self deleteSectionView:sectionView withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)deleteSectionView:(UIView *)sectionView withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewSectionViewKind kind;
    NSInteger sectionIndex = [self indexForSectionView:sectionView kind:&kind];
    if(sectionIndex!=NSNotFound){
        [self setSectionView:nil atIndex:sectionIndex kind:kind withAnimation:animation];
    }
}
- (void)deleteAllSections{
    [self deleteAllSectionsWithAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)deleteAllSectionsWithAnimation:(MKUIListViewItemAnimation)animation{
    NSInteger numberOfSections = self.numberOfSections;
    for (int i=0; i<numberOfSections; i++) {
        [self deleteSectionAtIndex:numberOfSections-i-1 withAnimation:animation];
    }
}
- (void)reloadSection:(NSInteger)sectionIndex{
    [self reloadSection:sectionIndex withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadSection:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation{
    [self _beforeUpdateAttributes];
    
    NSArray<MKUIListViewAttribute *> *attrsInSection = [self _attributesWithSectionIndex:sectionIndex];
    NSArray<MKUIListViewAttribute *> *nextAttrs = [self _attributesAfterSectionIndex:sectionIndex];
    for (MKUIListViewAttribute *attr in attrsInSection) {
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeReload) animation:animation]];
    }
    for (MKUIListViewAttribute *attr in nextAttrs) {
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeUpdate) animation:animation]];
    }
    
    //reload分组背景
    NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *sectionBgAttrs = [self _sectionGroupBackgroundAttributesAtOrAfterSection:sectionIndex];
    [self _reloadSectionGroupBackgroundAttributes:sectionBgAttrs withAnimation:(animation)];
    
    [self _afterUpdateAttributes];
}
- (void)reloadSectionView:(nullable UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind{
    [self reloadSectionView:sectionView atIndex:sectionIndex kind:kind withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadSectionView:(UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewSectionViewAttribute *sectionAttr = self.attributeMap[[MKUIListViewSectionViewAttribute dictionaryKeyWithSectionIndex:sectionIndex kind:kind]];
    if(!sectionAttr&&!sectionView){
        return;
    }
    [self _beforeUpdateAttributes];
    
    if(sectionAttr && sectionView==sectionAttr.modelView){
        [self _reloadAttributes:@[sectionAttr] withAnimation:(animation)];
    }else{
        if(sectionAttr){
            [self _removeAttributes:@[sectionAttr] withAnimation:animation];
        }
        if(sectionView){
            MKUIListViewSectionViewAttribute *newSectionAttr = [[MKUIListViewSectionViewAttribute alloc] initWithSectionIndex:sectionAttr.sectionIndex kind:sectionAttr.kind view:sectionView];
            [self _insertAttributes:@[newSectionAttr] withAnimation:animation];
        }
    }
    
    [self _afterUpdateAttributes];
}
- (void)reloadListHeaderView:(nullable UIView *)view{
    [self reloadListHeaderView:view withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadListHeaderView:(UIView *)view withAnimation:(MKUIListViewItemAnimation)animation{
    [self reloadListHeadFootView:view kind:(MKUIListViewHeadFootViewKindOfHead) withAnimation:animation];
}
- (void)reloadListFooterView:(nullable UIView *)view{
    [self reloadListFooterView:view withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadListFooterView:(nullable UIView *)view withAnimation:(MKUIListViewItemAnimation)animation{
    [self reloadListHeadFootView:view kind:(MKUIListViewHeadFootViewKindOfFoot) withAnimation:animation];
}
- (void)reloadListHeadFootView:(UIView *)view kind:(MKUIListViewHeadFootViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewHeadFootViewAttribute *attr = self.attributeMap[[MKUIListViewHeadFootViewAttribute dictionaryKeyWithKind:kind]];
    if(!attr && !view){
        return;
    }
    [self _beforeUpdateAttributes];
    if(attr && view==attr.modelView){
        [self _reloadAttributes:@[attr] withAnimation:(animation)];
    }else{
        if(attr){
            [self _removeAttributes:@[attr] withAnimation:animation];
        }
        if(view){
            MKUIListViewHeadFootViewAttribute *newAttr = [[MKUIListViewHeadFootViewAttribute alloc] initWithKind:kind view:view];
            [self _insertAttributes:@[newAttr] withAnimation:animation];
        }
    }
    [self _afterUpdateAttributes];
}
- (void)reloadSectionView:(UIView *)sectionView{
    [self reloadSectionView:sectionView withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadSectionView:(UIView *)sectionView withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewSectionViewAttribute *sectionAttr = self.attributeAddressMap[sectionView.mk_objectAddress];
    if(!sectionAttr){
        return;
    }
    [self reloadSectionView:sectionView atIndex:sectionAttr.sectionIndex kind:sectionAttr.kind withAnimation:animation];
}
- (void)insertItem:(UIView *)cell atIndexPath:(NSIndexPath *)indexPath{
    [self insertItem:cell atIndexPath:indexPath withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)insertItem:(UIView *)cell atIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation{
    if(!cell){
        return;
    }
    MKUIListViewCellAttribute *cellAttr = nil;
    //判断cell是否被标记删除了
    MKUIListViewPerformOperation *operation = [self _performOpertionForView:cell];
    if(operation){
        switch (operation.type) {
            case MKUIListViewPerformTypeAdd://重复添加,取消此次操作
            case MKUIListViewPerformTypeReload:
            case MKUIListViewPerformTypeUpdate:
                return;
                break;
            case MKUIListViewPerformTypeRemove://标记删除后，又添加上
                if(![operation.attribute isKindOfClass:MKUIListViewCellAttribute.class]) return;//标记删除时不为cell，后续又以cell身份添加上，则忽略此次的添加
                cellAttr = (MKUIListViewCellAttribute *)operation.attribute;//attribute使用被标志删除时的数据
                cellAttr.indexPath = indexPath;
                break;
            default:
                return;
                break;
        }
    }else{
        if(self.attributeAddressMap[cell.mk_objectAddress]){//重复添加，取消此次操作
            return;
        }
    }
    
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:indexPath.section];
    if(!sectionModel){
        return;
    }
    [self _beforeUpdateAttributes];
    
    if(!cellAttr)cellAttr = [[MKUIListViewCellAttribute alloc] initWithIndexPath:indexPath view:cell];
    [self _insertAttributes:@[cellAttr] withAnimation:animation];
    
    [self _afterUpdateAttributes];
}
- (void)addItem:(UIView *)cell atSectionIndex:(NSInteger)sectionIndex{
    [self addItem:cell atSectionIndex:sectionIndex withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)addItem:(UIView *)cell atSectionIndex:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation{
    if(sectionIndex<0||sectionIndex>=self.numberOfSections){
        return;
    }
    NSInteger cellIndex = [self numberOfItemsInSection:sectionIndex];
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:cellIndex inSection:sectionIndex];
    [self insertItem:cell atIndexPath:indexPath withAnimation:animation];
}
- (void)addItem:(UIView *)cell{
    [self addItem:cell withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)addItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewSectionAttributeModel *sectionModel = self.sectionModels.lastObject;
    if(!sectionModel){
        [self insertSectionAtIndex:self.numberOfSections];
        sectionModel = self.sectionModels.lastObject;
    }
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sectionModel.numberOfItems inSection:sectionModel.sectionIndex];
    [self insertItem:cell atIndexPath:indexPath withAnimation:animation];
}
- (void)deleteItemAtIndexPath:(NSIndexPath *)indexPath{
    [self deleteItemAtIndexPath:indexPath withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)deleteItemAtIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewCellAttribute *cellAttr = [self _cellAttributeAtIndexPath:indexPath];
    if(!cellAttr) return;
    
    [self _beforeUpdateAttributes];
    
    NSMutableArray<MKUIListViewAttribute *> *deleteAttrs = [[NSMutableArray alloc] initWithCapacity:2];
    [deleteAttrs addObject:cellAttr];
    
    [self _removeAttributes:@[cellAttr] withAnimation:animation];
    
    [self _afterUpdateAttributes];
}
- (void)deleteItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation{
    NSIndexPath *indexPath = [self indexPathForCell:cell];
    if(indexPath){
        [self deleteItemAtIndexPath:indexPath withAnimation:animation];
    }
}
- (void)reloadItemAtIndexPath:(NSIndexPath *)indexPath{
    [self reloadItemAtIndexPath:indexPath withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadItemAtIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewCellAttribute *cellAttr = [self _cellAttributeAtIndexPath:indexPath];
    if(!cellAttr){
        return;
    }
    
    [self _beforeUpdateAttributes];
    
    [self _reloadAttributes:@[cellAttr] withAnimation:animation];
    
    [self _afterUpdateAttributes];
}
- (void)reloadItem:(UIView *)cell{
    [self reloadItem:cell withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation{
    NSIndexPath *indexPath = [self indexPathForCell:cell];
    if(indexPath){
        [self reloadItem:cell atIndexPath:indexPath withAnimation:animation];
    }
}
- (void)reloadItem:(nullable UIView *)cell atIndexPath:(NSIndexPath *)indexPath{
    [self reloadItem:cell atIndexPath:indexPath withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadItem:(nullable UIView *)cell atIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation{
    MKUIListViewCellAttribute *cellAttr = [self _cellAttributeAtIndexPath:indexPath];
    if(!cellAttr&&!cell){
        return;
    }
    [self _beforeUpdateAttributes];
    
    if(cellAttr && cell==cellAttr.modelView){
        [self _reloadAttributes:@[cellAttr] withAnimation:animation];
    }else{
        if(cellAttr){
            [self _removeAttributes:@[cellAttr] withAnimation:animation];
        }
        if(cell){
            MKUIListViewCellAttribute *newCellAttr = [[MKUIListViewCellAttribute alloc] initWithIndexPath:cellAttr.indexPath?:indexPath view:cell];
            [self _insertAttributes:@[newCellAttr] withAnimation:animation];
        }
    }
    
    [self _afterUpdateAttributes];
}
- (void)moveItemFromIndexPath:(NSIndexPath *)fromIndexPath to:(NSIndexPath *)toIndexPath{
    [self moveItemFromIndexPath:fromIndexPath to:toIndexPath withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)moveItemFromIndexPath:(NSIndexPath *)fromIndexPath to:(NSIndexPath *)toIndexPath withAnimation:(MKUIListViewItemAnimation)animation{
    if([fromIndexPath isEqual:toIndexPath]) return;
    MKUIListViewCellAttribute *cellAttr = [self _cellAttributeAtIndexPath:fromIndexPath];
    MKUIListViewCellAttribute *toCellAttr = [self _cellAttributeAtIndexPath:toIndexPath];
    if(!toCellAttr){
        toCellAttr = [self _cellAttributeAtIndexPath:[NSIndexPath indexPathForItem:toIndexPath.item-1 inSection:toIndexPath.section]];
    }
    if(!cellAttr || !toCellAttr){
        return;
    }
    [self _beforeUpdateAttributes];
    
    [self _removeAttributes:@[cellAttr] withAnimation:animation];
    cellAttr.indexPath = toIndexPath;
    [self _insertAttributes:@[cellAttr] withAnimation:animation];
    
    [self _afterUpdateAttributes];
}
- (void)deleteView:(UIView *)view{
    [self deleteView:view withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)deleteView:(UIView *)view withAnimation:(MKUIListViewItemAnimation)animation{
    if(!view){
        return;
    }
    MKUIListViewAttribute *attr = self.attributeAddressMap[view.mk_objectAddress];
    if(!attr){
        return;
    }
    if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
        [self deleteItem:view withAnimation:animation];
    }else if([attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        [self deleteSectionView:view withAnimation:animation];
    }else if([attr isKindOfClass:[MKUIListViewHeadFootViewAttribute class]]){
        MKUIListViewHeadFootViewAttribute *headFootAttr = (MKUIListViewHeadFootViewAttribute *)attr;
        [self setListHeadFootView:nil kind:headFootAttr.kind withAnimation:animation];
    }
}
- (void)reloadView:(UIView *)view{
    [self reloadView:view withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadView:(UIView *)view withAnimation:(MKUIListViewItemAnimation)animation{
    if(!view){
        return;
    }
    MKUIListViewAttribute *attr = self.attributeAddressMap[view.mk_objectAddress];
    if(!attr){
        return;
    }
    if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
        [self reloadItem:view withAnimation:animation];
    }else if([attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        [self reloadSectionView:view withAnimation:animation];
    }else if([attr isKindOfClass:[MKUIListViewHeadFootViewAttribute class]]){
        MKUIListViewHeadFootViewAttribute *headFootAttr = (MKUIListViewHeadFootViewAttribute *)attr;
        [self reloadListHeadFootView:view kind:headFootAttr.kind withAnimation:animation];
    }
}
- (void)reloadData{
    [self _reloadDataWithAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)reloadDataWithAnimation:(MKUIListViewItemAnimation)animation{
    [self _reloadDataWithAnimation:(animation)];
}
- (void)reloadDataWithAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion{
    [self performBatchUpdates:^{
        [self _reloadDataWithAnimation:(animated?MKUIListViewItemAnimationAutomatic:MKUIListViewItemAnimationNone)];
    } animated:animated completion:completion];
}
- (UIView *)listHeadFootViewWithKind:(MKUIListViewHeadFootViewKind)kind{
    MKUIListViewHeadFootViewAttribute *attr = self.attributeMap[[MKUIListViewHeadFootViewAttribute dictionaryKeyWithKind:(kind)]];
    return attr.modelView;
}
- (UIView *)listHeaderView{
    return [self listHeadFootViewWithKind:(MKUIListViewHeadFootViewKindOfHead)];
}
- (UIView *)listFooterView{
    return [self listHeadFootViewWithKind:(MKUIListViewHeadFootViewKindOfFoot)];
}
- (void)setListHeadFootView:(UIView *)newView kind:(MKUIListViewHeadFootViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation{
    UIView *oldView = [self listHeadFootViewWithKind:kind];
    if(newView==oldView){
        return;
    }
    MKUIListViewHeadFootViewAttribute *newAttr = nil;
    if(newView){
        MKUIListViewPerformOperation *opertaion = [self _performOpertionForView:newView];
        if(opertaion){
            switch (opertaion.type) {
                case MKUIListViewPerformTypeAdd://重复添加，取消此次操作
                case MKUIListViewPerformTypeReload:
                case MKUIListViewPerformTypeUpdate:
                    return;
                    break;
                case MKUIListViewPerformTypeRemove://标记为删除，再次添加
                    if(![opertaion.attribute isKindOfClass:[MKUIListViewHeadFootViewAttribute class]])return;
                    newAttr = (MKUIListViewHeadFootViewAttribute *)opertaion.attribute;
                    newAttr.kind = kind;
                    break;
                default:
                    break;
            }
        }
    }
    
    [self _beforeUpdateAttributes];
    
    if(oldView){
        MKUIListViewHeadFootViewAttribute *oldAttr = self.attributeMap[[MKUIListViewHeadFootViewAttribute dictionaryKeyWithKind:kind]];
        if(oldAttr){
            [self _removeAttributes:@[oldAttr] withAnimation:animation];
        }
    }
    if(newView){
        if(!newAttr) newAttr = [[MKUIListViewHeadFootViewAttribute alloc] initWithKind:kind view:newView];
        [self _insertAttributes:@[newAttr] withAnimation:animation];
    }
    
    [self _afterUpdateAttributes];
}
- (void)setListHeaderView:(UIView *)listHeaderView{
    [self setListHeadFootView:listHeaderView kind:(MKUIListViewHeadFootViewKindOfHead) withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)setListFooterView:(UIView *)listFooterView{
    [self setListHeadFootView:listFooterView kind:(MKUIListViewHeadFootViewKindOfFoot) withAnimation:(MKUIListViewItemAnimationNone)];
}
- (void)setBackgroundView:(UIView *)backgroundView{
    if(_backgroundView!=backgroundView){
        if(_backgroundView){
            [_backgroundView removeFromSuperview];
        }
        _backgroundView = backgroundView;
        if(_backgroundView){
            [self addSubview:_backgroundView];
            [self sendSubviewToBack:_backgroundView];
        }
        [self _reloadBackgroundView];
    }
}
- (CGSize)sizeThatFits:(CGSize)size{
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    UIEdgeInsets insets = self.mk_adjustedContentInset;
    CGSize fitSizes = CGSizeZero;
    
    //刷新一下待变更操作中的单元格
    for (MKUIListViewPerformOperation *performOperation in self.performOperations.allValues) {
        MKUIListViewAttribute *attr = performOperation.attribute;
        if(![attr isKindOfClass:MKUIListViewCellAttribute.class]){
            continue;
        }
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        [cellAttr configAttributeWithListView:self];
    }
    
    CGSize contentSize = [self _calContentSizeWithAttributes:self.attributes inBounds:CGRectMake(0, 0, size.width, size.height) sizeFits:YES];
    MKCGSizeSetLength(&fitSizes, X, MKCGSizeGetLength(size, X));
    MKCGSizeSetLength(&fitSizes, Y, MKCGSizeGetLength(contentSize, Y));
    if(MKCGSizeGetLength(fitSizes, Y)>0){
        MKCGSizeAddLength(&fitSizes, Y, MKUIEdgeInsetsGetEdgeSum(insets, Y));
    }
    return fitSizes;
}
#pragma mark - private
- (NSInteger)_insertedIndexWithAttribute:(MKUIListViewAttribute *)attr{
    NSInteger index = [self.attributes mk_indexOfSortedObject:attr asc:YES];
    return index;
}
- (MKUIListViewSectionViewAttribute *)_sectionAttributeWithSectionIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind{
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex!=sectionIndex){
            return [@(arrayObj.sectionIndex) compare:@(sectionIndex)];
        }
        if([arrayObj isKindOfClass:MKUIListViewSectionViewAttribute.class]){
            MKUIListViewSectionViewAttribute *sectionAttr = (MKUIListViewSectionViewAttribute *)arrayObj;
            return [@(sectionAttr.kind) compare:@(kind)];
        }else if(kind==MKUIListViewSectionViewKindOfFoot){
            return NSOrderedAscending;
        }else{
            return NSOrderedDescending;
        }
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list.firstObject;
}
- (NSArray<MKUIListViewAttribute *> *)_attributesWithSectionIndex:(NSInteger)sectionIndex{
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        return [@(arrayObj.sectionIndex) compare:@(sectionIndex)];
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (MKUIListViewSectionViewAttribute *)_attributesWithSectionIndex:(NSInteger)sectionIndex sectionViewKind:(MKUIListViewSectionViewKind)kind{
    NSIndexPath *sortedIndexPath = [MKUIListViewSectionViewAttribute sortedIndexPathWithSectionIndex:sectionIndex kind:kind];
    return [self.attributes mk_subarrayOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *arrayObj, NSInteger idx) {
        return [arrayObj.sortedIndexPath compare:sortedIndexPath];
    }].firstObject;
}
- (MKUIListViewHeadFootViewAttribute *)_attributeWithListHeadFootViewKind:(MKUIListViewHeadFootViewKind)kind{
    MKUIListViewAttribute *attr = (kind==MKUIListViewHeadFootViewKindOfHead)?self.attributes.firstObject:self.attributes.lastObject;
    if([attr isKindOfClass:MKUIListViewHeadFootViewAttribute.class]){
        MKUIListViewHeadFootViewAttribute *headFootAttr = (MKUIListViewHeadFootViewAttribute *)attr;
        if(headFootAttr.kind==kind){
            return headFootAttr;
        }
    }
    return nil;
}
- (NSArray<MKUIListViewAttribute *> *)_attributesAfterOrAtSectionIndex:(NSInteger)sectionIndex{
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex>=sectionIndex){
            return NSOrderedSame;
        }else{
            return NSOrderedAscending;
        }
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (NSArray<MKUIListViewAttribute *> *)_attributesAfterSectionIndex:(NSInteger)sectionIndex{
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex>sectionIndex){
            return NSOrderedSame;
        }else{
            return NSOrderedAscending;
        }
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (NSArray<MKUIListViewAttribute *> *)_attributesAfterOrEqualSectionIndex:(NSInteger)sectionIndex{
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex>=sectionIndex){
            return NSOrderedSame;
        }else{
            return NSOrderedAscending;
        }
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (NSArray<MKUIListViewAttribute *> *)_attributesAfter:(MKUIListViewAttribute *)attr contain:(BOOL)contain{//contain是否包含attr
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        NSComparisonResult r = [arrayObj compare:attr];
        if(r==NSOrderedSame){
            if(contain){
                return NSOrderedSame;
            }else{
                return NSOrderedAscending;
            }
        }else if(r==NSOrderedDescending){
            return NSOrderedSame;
        }else{
            return r;
        }
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (NSArray<MKUIListViewAttribute *> *)_attributesBefore:(MKUIListViewAttribute *)attr contain:(BOOL)contain{//contain是否包含attr
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        NSComparisonResult r = [arrayObj compare:attr];
        if(r==NSOrderedSame){
            if(contain){
                return NSOrderedSame;
            }else{
                return NSOrderedDescending;
            }
        }else if(r==NSOrderedAscending){
            return NSOrderedSame;
        }else{
            return r;
        }
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (NSArray<MKUIListViewCellAttribute *> *)_cellAttributesInSection:(NSInteger)section{
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex>section) return NSOrderedDescending;
        if(arrayObj.sectionIndex<section) return NSOrderedAscending;
        if([arrayObj isKindOfClass:MKUIListViewSectionViewAttribute.class]){
            MKUIListViewSectionViewAttribute *sectionViewAttr = (MKUIListViewSectionViewAttribute *)arrayObj;
            if(sectionViewAttr.kind==MKUIListViewSectionViewKindOfHead) return NSOrderedAscending;
            return NSOrderedDescending;
        }
        return NSOrderedSame;
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (NSArray<MKUIListViewCellAttribute *> *)_cellAttributesInSectionAfter:(MKUIListViewAttribute *)attr contain:(BOOL)contain{
    NSMutableArray<MKUIListViewCellAttribute *> *result = [[NSMutableArray alloc] init];
    NSArray<MKUIListViewAttribute *> *attributes = [self _attributesInSectionAfter:attr contain:contain];
    for (MKUIListViewAttribute *attr in attributes) {
        if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
            [result addObject:(MKUIListViewCellAttribute *)attr];
        }
    }
    return result;
}
- (NSArray<MKUIListViewAttribute *> *)_attributesInSectionAfter:(MKUIListViewAttribute *)attr contain:(BOOL)contain{//contain是否包含attr
    if([attr isKindOfClass:[MKUIListViewHeadFootViewAttribute class]]){
        return nil;
    }
    NSInteger sectionIndex = attr.sectionIndex;
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex==sectionIndex){
            NSComparisonResult r = [arrayObj compare:attr];
            if(r==NSOrderedSame){
                if(contain){
                    return NSOrderedSame;
                }else{
                    return NSOrderedAscending;
                }
            }else if(r==NSOrderedDescending){
                return NSOrderedSame;
            }else{
                return NSOrderedAscending;
            }
        }else{
            return [@(arrayObj.sectionIndex) compare:@(sectionIndex)];;
        }
    }];
    NSArray *list = range.length!=0?[self.attributes subarrayWithRange:range]:nil;
    return list;
}
- (MKUIListViewSectionGroupBackgroundViewAttribute *)_sectionGroupBackgroundAttributesAtSection:(NSInteger)sectionIndex{
    if(!(sectionIndex>=0&&sectionIndex<self.sectionGroupBacgroundAttributes.count))return nil;
    return self.sectionGroupBacgroundAttributes[sectionIndex];
}
- (NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *)_sectionGroupBackgroundAttributesAtOrAfterSection:(NSInteger)sectionIndex{
    return [self.sectionGroupBacgroundAttributes mk_subarrayOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewSectionGroupBackgroundViewAttribute *arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex>=sectionIndex) return NSOrderedSame;
        return NSOrderedAscending;
    }];
}
- (NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *)_sectionGroupBackgroundAttributesAfterSection:(NSInteger)sectionIndex{
    return [self.sectionGroupBacgroundAttributes mk_subarrayOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewSectionGroupBackgroundViewAttribute *arrayObj, NSInteger idx) {
        if(arrayObj.sectionIndex>sectionIndex) return NSOrderedSame;
        return NSOrderedAscending;
    }];
}
- (NSArray<MKUIListViewAttribute *> *)_visiableAttributes{
    if(CGSizeEqualToSize(self.bounds.size, CGSizeZero)){
        return nil;
    }
    return [self _attributesInRect:[self _realVisiableBounds]];
}
- (NSArray<MKUIListViewAttribute *> *)_attributesInRect:(CGRect)rect{
    MKCGAxis Y = self.scrollAxis;
    CGRect contentRect = [self convertRect:rect toView:self.contentView];
    NSArray<MKUIListViewAttribute *> *result = nil;
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute *  _Nonnull attr, NSInteger idx) {
        return MKCGRectCompareWithCGRect(attr.frame, contentRect, Y);
    }];
    
    if(range.length>0){
        result = [self.attributes subarrayWithRange:range];
    }
    return result;
}
- (MKUIListViewAttribute *)_attributeAtPoint:(CGPoint)point{
    MKCGAxis Y = self.scrollAxis;
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute * _Nonnull arrayObj, NSInteger idx) {
        return MKCGRectCompareWithPoint(arrayObj.frame, point, Y);
    }];
    MKUIListViewAttribute *attr;
    if(range.location!=NSNotFound){
        attr = self.attributes[range.location];
    }
    return attr;
}
- (MKUIListViewAttribute *)_attributeNearestToPoint:(CGPoint)point{//最接近point的视图
    MKCGAxis Y = self.scrollAxis;
    NSInteger count = self.attributes.count;
    NSRange range = [self.attributes mk_rangeOfSortedObjectsWithComparator:^NSComparisonResult(MKUIListViewAttribute * _Nonnull arrayObj, NSInteger idx) {
        NSComparisonResult r = MKCGRectCompareWithPoint(arrayObj.frame, point, Y);
        if(r==NSOrderedSame) return r;
        if(r==NSOrderedAscending){
            //左侧
            if(idx==count-1){//右侧没有内容了
                return NSOrderedSame;
            }
            MKUIListViewAttribute *nextObj = self.attributes[idx+1];
            NSComparisonResult r1 = MKCGRectCompareWithPoint(nextObj.frame, point, Y);
            if(r1==NSOrderedSame) return NSOrderedSame;
            if(r1==NSOrderedDescending) return NSOrderedSame;
            return r;
        }else{
            //右侧
            if(idx==0){//左侧没有内容了
                return NSOrderedSame;
            }
            MKUIListViewAttribute *preObj = self.attributes[idx-1];
            NSComparisonResult r1 = MKCGRectCompareWithPoint(preObj.frame, point, Y);
            if(r1==NSOrderedSame) return NSOrderedSame;
            if(r1==NSOrderedAscending) return NSOrderedSame;
            return r;
        }
        return r;
    }];
    MKUIListViewAttribute *attr;
    if(range.location!=NSNotFound){
        CGFloat minDis = CGFLOAT_MAX;
        for(int i=0;i<range.length;i++){
            MKUIListViewAttribute *a = self.attributes[i+range.location];
            CGRect frame = a.frame;
            CGFloat dis = ABS(MKCGPointGetValue(point, Y)-MKCGRectGetMid(frame, Y));
            if(dis<minDis){
                minDis = dis;
                attr = a;
            }
        }
    }
    return attr;
}
- (void)_removeAttribute:(MKUIListViewAttribute *)attr withAnimation:(MKUIListViewItemAnimation)animation{
    if(!attr) return;
    [self _removeAttributes:@[attr] withAnimation:(animation)];
}
- (void)_removeAttributes:(NSArray<__kindof MKUIListViewAttribute *> *)attrs withAnimation:(MKUIListViewItemAnimation)animation{
    if(attrs.count==0) return;
    MKUIListViewAttribute *firstAttr = nil;
    for (MKUIListViewAttribute *attr in attrs) {
        NSRange range = [self.attributes mk_rangeOfSortedObject:attr asc:YES];
        if(range.length==0){
            continue;
        }
        if(!firstAttr || [firstAttr compare:attr]==NSOrderedAscending){
            firstAttr = attr;
        }
        
        MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:attr.sectionIndex];
        NSArray<MKUIListViewCellAttribute *> *nextCellAttrsInSection = [self _cellAttributesInSectionAfter:attr contain:NO];
        
        [self.attributes removeObjectsInRange:range];
        if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
            sectionModel.numberOfItems--;
        }
        
        [self.attributeMap removeObjectForKey:[attr dictionaryKey]];
        [self.attributeAddressMap removeObjectForKey:attr.modelView.mk_objectAddress];
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeRemove) animation:animation]];
        
        //更新后续cell的indexPath
        if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
            for (MKUIListViewCellAttribute *cellAttr in nextCellAttrsInSection) {
                cellAttr.itemIndex--;
                self.attributeMap[cellAttr.dictionaryKey] = cellAttr;
            }
        }
        MKUIListViewCellAttribute *nextCellAttr = nextCellAttrsInSection.firstObject;
        //更新后续的分隔符
        if([nextCellAttr isKindOfClass:MKUIListViewCellAttribute.class]){
            [self _updateSeparatorInSectionWithBeginCellAttribute:(MKUIListViewCellAttribute *)nextCellAttr animation:animation];
        }
        //更新分组样式
        if([self hasInsetGrouped]){
            [self __updateGroupAttributesWithBeginAttribute:nextCellAttr animation:animation];
        }
        
        //reload分组背景
        MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = [self _sectionGroupBackgroundAttributesAtSection:attr.sectionIndex];
        [self _reloadSectionGroupBackgroundAttribute:sectionBgAttr withAnimation:animation];
    }
    if(firstAttr){
        NSArray<__kindof MKUIListViewAttribute *> *nextAttrs = [self _attributesAfter:firstAttr contain:YES];
        for (MKUIListViewAttribute *nextAttr in nextAttrs) {
            [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:nextAttr type:(MKUIListViewPerformTypeUpdate) animation:animation]];
        }
        //update分组背景
        NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *sectionBgAttributes = [self _sectionGroupBackgroundAttributesAfterSection:firstAttr.sectionIndex];
        [self _updateSectionGroupBackgroundAttributes:sectionBgAttributes withAnimation:animation];
    }
}
- (void)_insertAttribute:(MKUIListViewAttribute *)attr withAnimation:(MKUIListViewItemAnimation)animation{
    if(!attr) return;
    [self _insertAttributes:@[attr] withAnimation:(animation)];
}
- (void)_insertAttributes:(NSArray<__kindof MKUIListViewAttribute *> *)attrs withAnimation:(MKUIListViewItemAnimation)animation{
    if(attrs.count==0) return;
    MKUIListViewAttribute *firstAttr = nil;
    for (int i=0; i<attrs.count; i++) {
        MKUIListViewAttribute *attr = attrs[i];
        if(!firstAttr || [firstAttr compare:attr]==NSOrderedAscending){
            firstAttr = attr;
        }
        NSInteger sectionIndex = attr.sectionIndex;
        MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:sectionIndex];
        NSArray<MKUIListViewCellAttribute *> *nextCellAttrsInSection = [self _cellAttributesInSectionAfter:attr contain:YES];
        
        [self.attributes mk_insertSortdObject:attr asc:YES];
        
        self.attributeAddressMap[attr.modelView.mk_objectAddress] = attr;
        self.attributeMap[attr.dictionaryKey] = attr;
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeAdd) animation:animation]];
        
        if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
            sectionModel.numberOfItems++;
        }
        //更新后续cell的indexPath值
        if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
            for (MKUIListViewCellAttribute *nextCellAttr in nextCellAttrsInSection) {
                nextCellAttr.itemIndex++;
                self.attributeMap[nextCellAttr.dictionaryKey] = nextCellAttr;
            }
        }
        //更新分隔符
        if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
            [self _updateSeparatorInSectionWithBeginCellAttribute:(MKUIListViewCellAttribute *)attr animation:animation];
        }
        //更新分组样式
        if([self hasInsetGrouped]){
            [self __updateGroupAttributesWithBeginAttribute:attr animation:animation];
        }
        
        //reload分组背景
        MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = [self _sectionGroupBackgroundAttributesAtSection:attr.sectionIndex];
        [self _reloadSectionGroupBackgroundAttribute:sectionBgAttr withAnimation:animation];
    }
    if(firstAttr){
        NSArray<__kindof MKUIListViewAttribute *> *nextAttrs = [self _attributesAfter:firstAttr contain:NO];
        for (MKUIListViewAttribute *nextAttr in nextAttrs) {
            [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:nextAttr type:(MKUIListViewPerformTypeUpdate) animation:animation]];
        }
        //update分组背景
        NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *sectionBgAttributes = [self _sectionGroupBackgroundAttributesAfterSection:firstAttr.sectionIndex];
        [self _updateSectionGroupBackgroundAttributes:sectionBgAttributes withAnimation:animation];
    }
}
- (void)_scrollToAttribute:(__kindof MKUIListViewAttribute *)attribute atScrollPosition:(MKUIListViewScrollPosition)scrollPosition animated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion{
    if(!attribute){
        if(completion){
            completion(YES);
        }
        return;
    }
    CGPoint offset = [self _contentOffsetWithCellFrame:attribute.frame scrollPosition:scrollPosition];
    if(animated){
        [UIView animateWithDuration:0.25 animations:^{
            self.contentOffset = offset;
        } completion:completion];
    }else{
        self.contentOffset = offset;
        if(completion){
            completion(YES);
        }
    }
}
- (void)_reloadAttributes:(NSArray<__kindof MKUIListViewAttribute *> *)attributes withAnimation:(MKUIListViewItemAnimation)animation{
    if(attributes.count==0) return;
    NSArray<__kindof MKUIListViewAttribute *> *attrs = [attributes sortedArrayUsingComparator:^NSComparisonResult(MKUIListViewAttribute * _Nonnull obj1, MKUIListViewAttribute * _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];
    MKUIListViewAttribute *firstAttr = attrs.firstObject;
    NSInteger index = [self _insertedIndexWithAttribute:firstAttr];
    if(index==NSNotFound){
        index = self.attributes.count;
    }
    
    NSArray<__kindof MKUIListViewAttribute *> *nextAttrs = index<self.attributes.count?[self.attributes subarrayWithRange:NSMakeRange(index, self.attributes.count-index)]:nil;
    
    for (int i=0; i<attrs.count; i++) {
        MKUIListViewAttribute *attr = attrs[i];
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeReload) animation:animation]];
    }
    
    for (MKUIListViewAttribute *nextAttr in nextAttrs) {
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:nextAttr type:(MKUIListViewPerformTypeUpdate) animation:animation]];
    }
    
    //reload分组背景
    for(MKUIListViewAttribute *attr in attributes){
        MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = [self _sectionGroupBackgroundAttributesAtSection:attr.sectionIndex];
        [self _reloadSectionGroupBackgroundAttribute:sectionBgAttr withAnimation:animation];
    }
    //update分组背景
    NSArray<MKUIListViewSectionGroupBackgroundViewAttribute *> *sectionBgAttributes = [self _sectionGroupBackgroundAttributesAfterSection:firstAttr.sectionIndex];
    [self _updateSectionGroupBackgroundAttributes:sectionBgAttributes withAnimation:animation];
}
- (void)_beforeUpdateAttributes{
    
}
- (void)_afterUpdateAttributes{
    if(!self.performingBatchUpdates){
        [self _setNeedPerformBatchUpdates];
    }
}
- (void)_updateAttributes:(NSArray<__kindof MKUIListViewAttribute *> *)attributes withAnimation:(MKUIListViewItemAnimation)animation{
    if(attributes.count==0) return;
    NSArray<__kindof MKUIListViewAttribute *> *attrs = [attributes sortedArrayUsingComparator:^NSComparisonResult(MKUIListViewAttribute * _Nonnull obj1, MKUIListViewAttribute * _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];
    MKUIListViewAttribute *firstAttr = attrs.firstObject;
    NSInteger index = [self _insertedIndexWithAttribute:firstAttr];
    if(index==NSNotFound){
        index = self.attributes.count;
    }
    
    NSArray<__kindof MKUIListViewAttribute *> *nextAttrs = index<self.attributes.count?[self.attributes subarrayWithRange:NSMakeRange(index, self.attributes.count-index)]:nil;
    
    for (int i=0; i<attrs.count; i++) {
        MKUIListViewAttribute *attr = attrs[i];
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeUpdate) animation:animation]];
        
    }
    for (MKUIListViewAttribute *nextAttr in nextAttrs) {
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:nextAttr type:(MKUIListViewPerformTypeUpdate) animation:animation]];
    }
}
- (MKUIListViewPerformOperation *)_performOpertionForView:(UIView *)view{
    if(!view)return nil;
    MKUIListViewPerformOperation *op = self.performOperations[view.mk_objectAddress];
    return op;
}
- (void)_addPerformOperation:(MKUIListViewPerformOperation *)performOperation{
    UIView *view = performOperation.attribute.modelView?:performOperation.attribute.containerView;
    NSString *key = view.mk_objectAddress;
    MKUIListViewPerformOperation *old = self.performOperations[key];
    if(old){
        switch (old.type) {
            case MKUIListViewPerformTypeAdd:{
                if(performOperation.type==MKUIListViewPerformTypeRemove){
                    performOperation = nil;
                }else{
                    performOperation.type = old.type;
                }
            }
                break;
            case MKUIListViewPerformTypeRemove:{
                if(performOperation.type==MKUIListViewPerformTypeAdd){
                    performOperation.type = MKUIListViewPerformTypeReload;
                }else{
                    performOperation.type = old.type;
                }
            }
                break;
            case MKUIListViewPerformTypeReload:{
                if(performOperation.type==MKUIListViewPerformTypeAdd
                   ||performOperation.type==MKUIListViewPerformTypeUpdate
                   ){
                    performOperation.type = old.type;
                }
            }
                break;
            case MKUIListViewPerformTypeUpdate:{
                if(performOperation.type==MKUIListViewPerformTypeAdd){
                    performOperation.type = old.type;
                }
            }
                break;
            default:
                break;
        }
    }
    if(performOperation){
        self.performOperations[key] = performOperation;
    }else{
        [self.performOperations removeObjectForKey:key];
    }
}
- (CGSize)_calContentSizeWithAttributes:(NSArray<MKUIListViewAttribute *> *)attributes{
    return [self _calContentSizeWithAttributes:attributes inBounds:self.bounds sizeFits:NO];
}
//输入所有的视图属性，计算contentSize
- (CGSize)_calContentSizeWithAttributes:(NSArray<MKUIListViewAttribute *> *)attributes inBounds:(CGRect)bounds sizeFits:(BOOL)sizeFits{
    if(CGSizeEqualToSize(CGSizeZero, bounds.size)){
        return CGSizeZero;
    }
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    CGFloat sectionInteritemSpacing = self.sectionInteritemSpacing;
    BOOL needInsetGroup = [self hasInsetGrouped];
    UIEdgeInsets insets = self.mk_adjustedContentInset;
    bounds = UIEdgeInsetsInsetRect(bounds, insets);
    CGSize limitSize = bounds.size;
    if(MKCGSizeGetLength(limitSize, Y)==0) MKCGSizeSetLength(&limitSize, Y, 99999999);
    CGSize contentSize = CGSizeZero;
    CGFloat sum = 0;
    
    NSArray<_MKUIListViewAttributeCollection *> *attrCollections = [_MKUIListViewAttributeCollection attributeCollectionsWithAttributes:self.attributes];
    
    for(int i=0;i<attrCollections.count;i++){
        _MKUIListViewAttributeCollection *attrCollection = attrCollections[i];
        if(attrCollection.attributes.count==0)continue;
        UIEdgeInsets groupsInsets = UIEdgeInsetsZero;
        UIEdgeInsets groupsInnerInsets = UIEdgeInsetsZero;
        CGFloat cellInteritemSpacing = 0;
        if(needInsetGroup && attrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){//添加上分组的groupInsets
            groupsInsets = [self groupInsetsForSection:attrCollection.sectionIndex];
            groupsInnerInsets = [self groupInnerInsetsForSection:attrCollection.sectionIndex];
        }
        if(attrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){
            cellInteritemSpacing = [self cellInteritemSpacingForSection:attrCollection.sectionIndex];
        }
        sum += MKUIEdgeInsetsGetEdge(groupsInsets, Y, MKUIEdgeInsetsMin);
        NSArray<MKUIListViewAttribute *> *attributes = attrCollection.attributes;
        BOOL hasCellAttr = NO;
        for(int j=0;j<attributes.count;j++){
            __kindof MKUIListViewAttribute *attr = attributes[j];
            if(sizeFits){
                CGSize fitSize = [self _calAttribute:attr sizeThatFits:limitSize];
                sum += MKCGSizeGetLength(fitSize, Y);
            }else{
                sum += MKCGSizeGetLength(attr.frame.size, Y);
            }
            if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
                hasCellAttr = YES;
                MKUIListViewAttribute *nextAttr = j+1<attributes.count?attributes[j+1]:nil;
                if(nextAttr!=nil&&[nextAttr isKindOfClass:MKUIListViewCellAttribute.class]){
                    sum += cellInteritemSpacing;
                }
            }
        }
        if(hasCellAttr){
            sum += MKUIEdgeInsetsGetEdgeSum(groupsInnerInsets, Y);
        }
        sum += MKUIEdgeInsetsGetEdge(groupsInsets, Y, MKUIEdgeInsetsMax);
        if(attrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){
            _MKUIListViewAttributeCollection *nextAttrCollection = i+1<attrCollections.count?attrCollections[i+1]:nil;
            if(nextAttrCollection!=nil&&nextAttrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){
                sum += sectionInteritemSpacing;
            }
        }
    }
    
    sum = /*ceil*/(sum);//消除浮点误差
    MKCGSizeSetLength(&contentSize, X, MKCGRectGetLength(bounds, X));
    MKCGSizeSetLength(&contentSize, Y, sum);
    return contentSize;
}
//刷新背景视图
- (void)_reloadBackgroundView{
    if(self.backgroundView){
        MKCGAxis Y = self.scrollAxis;
        CGRect bounds = self.bounds;
        CGRect f1 = bounds;
        MKCGRectSetMin(&f1, Y, MKCGPointGetValue(self.contentOffset, Y));
        self.backgroundView.frame = f1;
        if(!self.backgroundView.superview){
            [self addSubview:self.backgroundView];
            [self sendSubviewToBack:self.backgroundView];
        }
    }
}
- (void)_updateSeparatorInSectionWithBeginCellAttribute:(MKUIListViewCellAttribute *)cellAttr animation:(MKUIListViewItemAnimation)animation{
    NSInteger section = cellAttr.sectionIndex;
    MKUIListViewCellAttribute *currentCellAttr = [self _cellAttributeAtIndexPath:[NSIndexPath indexPathForItem:cellAttr.itemIndex inSection:section]];
    MKUIListViewCellAttribute *preCellAttr = [self _cellAttributeAtIndexPath:[NSIndexPath indexPathForItem:cellAttr.itemIndex-1 inSection:section]];
    MKUIListViewCellAttribute *nextCellAttr = [self _cellAttributeAtIndexPath:[NSIndexPath indexPathForItem:cellAttr.itemIndex+1 inSection:section]];
    
    NSMutableArray<MKUIListViewAttribute *> *attrList = [[NSMutableArray alloc] init];
    if(cellAttr && ![attrList containsObject:cellAttr]){
        [attrList addObject:cellAttr];
    }
    if(preCellAttr && ![attrList containsObject:preCellAttr]){
        [attrList addObject:preCellAttr];
    }
    if(currentCellAttr && ![attrList containsObject:currentCellAttr]){
        [attrList addObject:currentCellAttr];
    }
    if(nextCellAttr && ![attrList containsObject:nextCellAttr]){
        [attrList addObject:nextCellAttr];
    }
    
    for (MKUIListViewCellAttribute *cellAttr in attrList) {
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:cellAttr type:(MKUIListViewPerformTypeReload) animation:animation]];
    }
}
- (CGRect)_realVisiableBounds{
    CGRect bounds = self.bounds;
    return bounds;
}
- (MKUIListViewSectionAttributeModel *)_sectionAttributeModelAtIndex:(NSInteger)sectionIndex{
    MKUIListViewSectionAttributeModel *sectionModel = nil;
    if(sectionIndex>=0&&sectionIndex<self.sectionModels.count){
        sectionModel = self.sectionModels[sectionIndex];
    }
    return sectionModel;
}
- (MKUIListViewCellAttribute *)_cellAttributeAtIndexPath:(NSIndexPath *)indexPath{
    return self.attributeMap[[MKUIListViewCellAttribute dictionaryKeyWithIndexPath:indexPath]];
}
- (void)_setNeedPerformBatchUpdates{
    _needPerformBatchUpdates = YES;
    [self setNeedsLayout];
}
- (void)_applyPerformOpertaionToAttributes{
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    CGRect bounds = self.mk_contentBounds;
    CGSize limitSize = bounds.size;
    if(MKCGSizeGetLength(limitSize, Y)==0) MKCGSizeSetLength(&limitSize, Y, 99999999);
    NSMutableArray<MKUIListViewPerformOperation *> *sectionBgAttributeOperations = [[NSMutableArray alloc] init];
    for (MKUIListViewPerformOperation *performOperation in self.performOperations.allValues) {
        MKUIListViewAttribute *attr = performOperation.attribute;
        if([attr isKindOfClass:MKUIListViewSectionGroupBackgroundViewAttribute.class]){
            [sectionBgAttributeOperations addObject:performOperation];
            continue;
        }
        UIView *view = attr.attributeView;
        if(!view){
            continue;
        }
        switch (performOperation.type) {
            case MKUIListViewPerformTypeAdd:
            case MKUIListViewPerformTypeReload:{
                [attr configAttributeWithListView:self];
                CGRect f1 = attr.frame;
                CGSize fitSize = [self _calAttribute:attr sizeThatFits:limitSize];
                MKCGRectSetLength(&f1, X, MKCGRectGetLength(bounds, X));
                MKCGRectSetLength(&f1, Y, /*ceil*/(MKCGSizeGetLength(fitSize, Y)));
                attr.frame = f1;
            }
                break;
            case MKUIListViewPerformTypeUpdate:
                break;
            default:
                break;
        }
        if(performOperation.type==MKUIListViewPerformTypeAdd){
            [self.contentView addSubview:view];
        }
    }
    for (MKUIListViewPerformOperation *performOperation in sectionBgAttributeOperations) {
        if(performOperation.type==MKUIListViewPerformTypeRemove||performOperation.type==MKUIListViewPerformTypeUpdate){
            continue;
        }
        MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = performOperation.attribute;
        if(performOperation.type==MKUIListViewPerformTypeAdd||performOperation.type==MKUIListViewPerformTypeReload){
            [sectionBgAttr configAttributeWithListView:self];
        }
        UIView *view = sectionBgAttr.attributeView;
        if(!view){
            continue;
        }
        UIEdgeInsets groupInnerInsets = UIEdgeInsetsZero;
        if([self hasInsetGrouped]){
            groupInnerInsets = [self groupInnerInsetsForSection:sectionBgAttr.sectionIndex];
        }
        CGFloat cellInteritemSpacing = [self cellInteritemSpacingForSection:sectionBgAttr.sectionIndex];
        //计算该分组下，所有cell的尺寸信息
        NSArray<MKUIListViewCellAttribute *> *cellAttrs = [self _cellAttributesInSection:sectionBgAttr.sectionIndex];
        CGFloat sum = 0;
        CGRect f1 = sectionBgAttr.frame;
        for(MKUIListViewCellAttribute *cellAttr in cellAttrs){
            sum += MKCGRectGetLength(cellAttr.frame, Y);
        }
        if(cellInteritemSpacing!=0&&cellAttrs.count>0){
            sum += cellInteritemSpacing*(cellAttrs.count-1);
        }
        if(cellAttrs.count>0){
            sum += MKUIEdgeInsetsGetEdgeSum(groupInnerInsets, Y);
        }
        MKCGRectSetLength(&f1, X, MKCGRectGetLength(bounds, X));
        MKCGRectSetLength(&f1, Y, sum);
        sectionBgAttr.frame = f1;
        
        if(performOperation.type==MKUIListViewPerformTypeAdd){
            [self.contentView addSubview:view];
            [self.contentView sendSubviewToBack:view];
        }
    }
}
- (void)_applyAttributeChangeWithAnimated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion{
    NSArray<MKUIListViewAttribute *> *oldVisiableAttributes = self.cachedVisiableAttributes;
    [self _applyPerformOpertaionToAttributes];
    [self _reloadAttributesWithFitSize:NO];
    [self _reloadSectionBackgroundAttributes];
    [self _reloadContentSize];
    [self _reloadBackgroundView];
    NSArray<MKUIListViewAttribute *> *newVisiableAttributes = [self _visiableAttributes];
    self.cachedVisiableAttributes = newVisiableAttributes;
    
    NSArray<MKUIListViewPerformOperation *> *performOperations = self.performOperations.allValues;
    _needPerformBatchUpdates = NO;
    if(animated){
        for (MKUIListViewPerformOperation *operation in performOperations) {
            [self _willPerformOperation:operation];
        }
        [UIView animateWithDuration:0.25 animations:^{
            for (MKUIListViewPerformOperation *operation in performOperations) {
                [self _performingOperation:operation];
            }
        } completion:^(BOOL finished) {
            for (MKUIListViewPerformOperation *operation in performOperations) {
                [self _didEndPerformOperation:operation];
                if(operation.type==MKUIListViewPerformTypeAdd){
                    [self _notifyAttributeViewDidAdd:operation.attribute];
                }
            }
            [self _cleanAttributeChange];
            [self _notifyVisiableAttributeChangeWithOld:oldVisiableAttributes newVisiableAttributes:newVisiableAttributes];
            for (MKUIListViewPerformOperation *operation in performOperations) {
                if(operation.type==MKUIListViewPerformTypeRemove){
                    [self _notifyAttributeViewDidRemove:operation.attribute];
                }
            }
            if(completion){
                completion(finished);
            }
        }];
    }else{
        for (MKUIListViewPerformOperation *operation in performOperations) {
            [self _didEndPerformOperation:operation];
            if(operation.type==MKUIListViewPerformTypeAdd){
                [self _notifyAttributeViewDidAdd:operation.attribute];
            }
        }
        [self _cleanAttributeChange];
        [self _notifyVisiableAttributeChangeWithOld:oldVisiableAttributes newVisiableAttributes:newVisiableAttributes];
        for (MKUIListViewPerformOperation *operation in performOperations) {
            if(operation.type==MKUIListViewPerformTypeRemove){
                [self _notifyAttributeViewDidRemove:operation.attribute];
            }
        }
        if(completion){
            completion(YES);
        }
    }
}
- (void)_cleanAttributeChange{
    [self.performOperations removeAllObjects];
}
- (CGPoint)_contentOffsetWithCellFrame:(CGRect)cellFrame scrollPosition:(MKUIListViewScrollPosition)position{
    CGRect cellFrame2 = [self.contentView convertRect:cellFrame toView:self];
    MKUIScrollViewScrollDirection direction = self.scrollDirection==MKUIListViewScrollDirectionVertical?MKUIScrollViewScrollDirectionVertical:MKUIScrollViewScrollDirectionHorizontal;
    MKUIScrollViewScrollPosition scrollPosition = MKUIScrollViewScrollPositionMiddle;
    switch (position) {
        case MKUIListViewScrollPositionNone:
            return self.contentOffset;
            break;
        case MKUIListViewScrollPositionHead:
            scrollPosition = MKUIScrollViewScrollPositionHead;
            break;
        case MKUIListViewScrollPositionMiddle:
            scrollPosition = MKUIScrollViewScrollPositionMiddle;
            break;
        case MKUIListViewScrollPositionFoot:
            scrollPosition = MKUIScrollViewScrollPositionFoot;
            break;
        default:
            return self.contentOffset;
            break;
    }
    CGPoint contentOffset = [self mk_contentOffsetWithScrollTo:cellFrame2 direction:direction position:scrollPosition];
    return contentOffset;
}
- (void)_reloadContentSize{
    CGSize contentSize = [self _calContentSizeWithAttributes:self.attributes];
    self.contentSize = contentSize;
    CGRect f1 = CGRectZero;
    f1.size = contentSize;
    self.contentView.frame = f1;
}
- (void)_reloadSectionBackgroundAttributes{
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    CGFloat sectionInteritemSpacing = self.sectionInteritemSpacing;
    CGRect bounds = self.mk_contentBounds;
    CGRect f1 = bounds;
    MKCGRectSetMin(&f1, Y, 0);
    MKCGRectSetLength(&f1, X, MKCGRectGetLength(bounds, X));
    MKCGRectSetLength(&f1, Y, 0);
    MKUIListViewHeadFootViewAttribute *headAttr = [self _attributeWithListHeadFootViewKind:(MKUIListViewHeadFootViewKindOfHead)];
    if(headAttr){
        MKCGRectAddMid(&f1, Y, MKCGRectGetLength(headAttr.frame, Y));
    }
    
    //设置zIndex值
    CGFloat zIndexBegin = 0.0-self.sectionGroupBacgroundAttributes.count;
    for (int i=0; i<self.sectionGroupBacgroundAttributes.count; i++) {
        MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = self.sectionGroupBacgroundAttributes[i];
        sectionBgAttr.zIndex = zIndexBegin+i;
    }
    BOOL needInsetGroup = [self hasInsetGrouped];
    for(int i=0;i<self.sectionGroupBacgroundAttributes.count;i++){
        MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = self.sectionGroupBacgroundAttributes[i];
        UIEdgeInsets groupInsets = needInsetGroup?sectionBgAttr.groupInsets:UIEdgeInsetsZero;
        MKUIListViewSectionViewAttribute *sectionHeadAttr = [self _attributesWithSectionIndex:i sectionViewKind:(MKUIListViewSectionViewKindOfHead)];
        MKUIListViewSectionViewAttribute *sectionFootAttr = [self _attributesWithSectionIndex:i sectionViewKind:(MKUIListViewSectionViewKindOfFoot)];
        NSInteger cellCount = [self numberOfItemsInSection:i];
        BOOL isEmptySection = sectionHeadAttr==nil&&sectionFootAttr==nil&&cellCount==0;
        
        if(!isEmptySection){//分组为非空分组
            MKCGRectAddMid(&f1, Y, MKUIEdgeInsetsGetEdge(groupInsets, Y, MKUIEdgeInsetsMin));
            if(sectionHeadAttr){
                MKCGRectAddMid(&f1, Y, MKCGRectGetLength(sectionHeadAttr.frame, Y));
            }
            MKCGRectSetLength(&f1, Y, MKCGSizeGetLength(sectionBgAttr.frame.size, Y));
            sectionBgAttr.frame = f1;
            if(sectionFootAttr){
                MKCGRectAddMid(&f1, Y, MKCGRectGetLength(sectionFootAttr.frame, Y));
            }
            MKCGRectAddMid(&f1, Y, MKUIEdgeInsetsGetEdge(groupInsets, Y, MKUIEdgeInsetsMax));
            MKCGRectAddMid(&f1, Y, MKCGRectGetLength(f1, Y));
            MKCGRectAddMid(&f1, Y, sectionInteritemSpacing);
            MKCGRectSetLength(&f1, Y, 0);
        }else{
            sectionBgAttr.frame = f1;
        }
    }
}
- (void)_reloadAttributesWithFitSize:(BOOL)fitSize{
    MKCGAxis Y = self.scrollAxis;
    CGFloat sectionInteritemSpacing = self.sectionInteritemSpacing;
    BOOL needInsetGroup = [self hasInsetGrouped];
    CGRect bounds = self.mk_contentBounds;
    CGSize limitSize = bounds.size;
    if(MKCGSizeGetLength(limitSize, Y)==0) MKCGSizeSetLength(&limitSize, Y, 99999999);
    CGRect f1 = bounds;
    MKCGRectSetMin(&f1, Y, 0);
    
    //设置zIndex值
    for (int i=0; i<self.attributes.count; i++) {
        MKUIListViewAttribute *attr = self.attributes[i];
        attr.zIndex = [self _calAttribute:attr zIndexFor:i];
    }
    NSArray<_MKUIListViewAttributeCollection *> *attrCollections = [_MKUIListViewAttributeCollection attributeCollectionsWithAttributes:self.attributes];
    
    for(int i=0;i<attrCollections.count;i++){
        _MKUIListViewAttributeCollection *attrCollection = attrCollections[i];
        if(attrCollection.attributes.count==0)continue;
        UIEdgeInsets groupsInsets = UIEdgeInsetsZero;
        UIEdgeInsets groupsInnerInsets = UIEdgeInsetsZero;
        CGFloat cellInteritemSpacing = 0;
        if(needInsetGroup && attrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){//添加上分组的groupInsets
            groupsInsets = [self groupInsetsForSection:attrCollection.sectionIndex];
            groupsInnerInsets = [self groupInnerInsetsForSection:attrCollection.sectionIndex];
        }
        if(attrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){
            cellInteritemSpacing = [self cellInteritemSpacingForSection:attrCollection.sectionIndex];
        }
        MKCGRectAddMin(&f1, Y, MKUIEdgeInsetsGetEdge(groupsInsets, Y, MKUIEdgeInsetsMin));
        NSArray<MKUIListViewAttribute *> *attributes = attrCollection.attributes;
        BOOL isFirstCell = NO;
        for(int j=0;j<attributes.count;j++){
            __kindof MKUIListViewAttribute *attr = attributes[j];
            if(fitSize){
                CGSize fitSize = [self _calAttribute:attr sizeThatFits:limitSize];
                MKCGRectSetLength(&f1, Y, /*ceil*/(MKCGSizeGetLength(fitSize, Y)));
            }else{
                MKCGRectSetLength(&f1, Y, MKCGSizeGetLength(attr.frame.size, Y));
            }
            if([attr isKindOfClass:MKUIListViewCellAttribute.class]&&!isFirstCell){
                isFirstCell = YES;
                MKCGRectAddMin(&f1, Y, MKUIEdgeInsetsGetEdge(groupsInnerInsets, Y, MKUIEdgeInsetsMin));
            }
            attr.frame = f1;
            MKCGRectAddMin(&f1, Y, MKCGRectGetLength(f1, Y));
            MKCGRectSetLength(&f1, Y, 0);
            if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
                MKUIListViewAttribute *nextAttr = j+1<attributes.count?attributes[j+1]:nil;
                if(nextAttr!=nil&&[nextAttr isKindOfClass:MKUIListViewCellAttribute.class]){
                    MKCGRectAddMin(&f1, Y, cellInteritemSpacing);
                }
                if(nextAttr==nil||![nextAttr isKindOfClass:MKUIListViewCellAttribute.class]){
                    MKCGRectAddMin(&f1, Y, MKUIEdgeInsetsGetEdge(groupsInnerInsets, Y, MKUIEdgeInsetsMax));
                }
            }
        }
        MKCGRectAddMin(&f1, Y, MKUIEdgeInsetsGetEdge(groupsInsets, Y, MKUIEdgeInsetsMax));
        if(attrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){
            _MKUIListViewAttributeCollection *nextAttrCollection = i+1<attrCollections.count?attrCollections[i+1]:nil;
            if(nextAttrCollection!=nil&&nextAttrCollection.type==_MKUIListViewAttributeCollectionTypeOfListViewSection){
                MKCGRectAddMin(&f1, Y, sectionInteritemSpacing);
            }
        }
    }
}
- (CGFloat)_calAttribute:(MKUIListViewAttribute *)attr zIndexFor:(CGFloat)zIndex{
    CGFloat calZIndex = zIndex;
    BOOL isCaled = NO;
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if(!isCaled && [attr isKindOfClass:MKUIListViewCellAttribute.class]){
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        if(!isCaled && delegate && [delegate respondsToSelector:@selector(listView:zIndexFor:forCell:forIndexPath:)]){
            calZIndex = [delegate listView:self zIndexFor:zIndex forCell:cellAttr.modelView forIndexPath:cellAttr.indexPath];
            //            isCaled = YES;
        }
        if(!isCaled && [attr.modelView conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [attr.modelView respondsToSelector:@selector(listView:zIndexFor:atIndexPath:)]){
            calZIndex = [(UIView<MKUIListCellViewProtocol> *)attr.modelView listView:self zIndexFor:zIndex atIndexPath:cellAttr.indexPath];
            //            isCaled = YES;
        }
    }
    if(!isCaled && [attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        MKUIListViewSectionViewAttribute *sectionAttr = (MKUIListViewSectionViewAttribute *)attr;
        if(!isCaled && delegate && [delegate respondsToSelector:@selector(listView:zIndexFor:forSectionView:forSection:kind:)]){
            calZIndex = [delegate listView:self zIndexFor:zIndex forSectionView:sectionAttr.modelView forSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            //            isCaled = YES;
        }
        if(!isCaled && [attr.modelView conformsToProtocol:@protocol(MKUIListSectionViewProtocol)] && [attr.modelView respondsToSelector:@selector(listView:zIndexFor:atSection:kind:)]){
            calZIndex = [(UIView<MKUIListSectionViewProtocol> *)attr.modelView listView:self zIndexFor:zIndex atSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            //            isCaled = YES;
        }
    }
    return calZIndex;
}
- (CGSize)_calAttribute:(MKUIListViewAttribute *)attr sizeThatFits:(CGSize)originSize{
    CGSize size = originSize;
    MKCGAxis Y = [self scrollAxis];
    MKCGAxis X = MKCGAxisReverse(Y);
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([self hasInsetGrouped] && ([attr isKindOfClass:MKUIListViewCellAttribute.class]||[attr isKindOfClass:MKUIListViewSectionViewAttribute.class])){//分组样式时，分组头、单元格，尾部视图，扣除groupInsets的边距
        UIEdgeInsets groupInsets = [self groupInsetsWithSafeAreaInsetsForSection:attr.sectionIndex];
        UIEdgeInsets groupInnerInsets = [self groupInnerInsetsForSection:attr.sectionIndex];
        MKCGSizeAddLength(&size, X, -MKUIEdgeInsetsGetEdgeSum(groupInsets, X));
        MKCGSizeAddLength(&size, X, -MKUIEdgeInsetsGetEdgeSum(groupInnerInsets, X));
    }
    CGSize fitSize = size;
    BOOL isCaled = NO;
    if(!isCaled && [attr isKindOfClass:MKUIListViewCellAttribute.class]){
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        if(!isCaled && delegate && [delegate respondsToSelector:@selector(listView:sizeThatFits:forCell:forIndexPath:)]){
            fitSize = [delegate listView:self sizeThatFits:size forCell:cellAttr.modelView forIndexPath:cellAttr.indexPath];
            isCaled = YES;
        }
        if(!isCaled && [attr.modelView conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [attr.modelView respondsToSelector:@selector(listView:sizeThatFits:atIndexPath:)]){
            fitSize = [(UIView<MKUIListCellViewProtocol> *)attr.modelView listView:self sizeThatFits:size atIndexPath:cellAttr.indexPath];
            isCaled = YES;
        }
        if(isCaled){
            if(cellAttr.hasSeparator){
                MKUIListViewCellAttributeContainerView *cellContainerView = cellAttr.cellContainerView;
                [cellContainerView applyAttribute:cellAttr];
                CGSize s1 = [cellContainerView.separatorView sizeThatFits:size];
                MKCGSizeAddLength(&fitSize, Y, MKCGSizeGetLength(s1, Y));//添加上分隔线的高度值
            }
        }
    }
    if(!isCaled && [attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        MKUIListViewSectionViewAttribute *sectionAttr = (MKUIListViewSectionViewAttribute *)attr;
        if(!isCaled && delegate && [delegate respondsToSelector:@selector(listView:sizeThatFits:forSectionView:forSection:kind:)]){
            fitSize = [delegate listView:self sizeThatFits:size forSectionView:sectionAttr.modelView forSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            isCaled = YES;
        }
        if(!isCaled && [attr.modelView conformsToProtocol:@protocol(MKUIListSectionViewProtocol)] && [attr.modelView respondsToSelector:@selector(listView:sizeThatFits:atSection:kind:)]){
            fitSize = [(UIView<MKUIListSectionViewProtocol> *)attr.modelView listView:self sizeThatFits:size atSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            isCaled = YES;
        }
    }
    if(!isCaled){
        fitSize = [attr.attributeView sizeThatFits:size];
    }
    return fitSize;
}
- (void)_reloadDataWithAnimation:(MKUIListViewItemAnimation)animation{
    [self _beforeUpdateAttributes];
    for (MKUIListViewAttribute *attr in self.attributes) {
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeReload) animation:animation]];
    }
    //reload分组背景
    for (MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr in self.sectionGroupBacgroundAttributes){
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:sectionBgAttr type:(MKUIListViewPerformTypeReload) animation:animation]];
    }
    
    [self _afterUpdateAttributes];
}
#pragma mark - private-notify
- (id<MKUIListViewDelegate>)_listViewDelegate{
    id<MKUIListViewDelegate> delegate = nil;
    if([self.delegate conformsToProtocol:@protocol(MKUIListViewDelegate)]){
        delegate = (id<MKUIListViewDelegate>)self.delegate;
    }
    return delegate;
}
- (void)_notifyAttributeViewDidRemove:(MKUIListViewAttribute *)attr{
    if(!attr){
        return;
    }
    if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        UIView *view = cellAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListCellViewProtocol)]){
            UIView<MKUIListCellViewProtocol> *cell = (UIView<MKUIListCellViewProtocol> *)view;
            if([cell respondsToSelector:@selector(listView:didDeleteAtIndexPath:)]){
                [cell listView:self didDeleteAtIndexPath:cellAttr.indexPath];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:didDeleteCell:forItemAtIndexPath:)]){
                [delegate listView:self didDeleteCell:view forItemAtIndexPath:cellAttr.indexPath];
            }
        }
    }else if([attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        MKUIListViewSectionViewAttribute *sectionAttr = (MKUIListViewSectionViewAttribute *)attr;
        UIView *view = sectionAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListSectionViewProtocol)]){
            UIView<MKUIListSectionViewProtocol> *setionView = (UIView<MKUIListSectionViewProtocol> *)view;
            if([setionView respondsToSelector:@selector(listView:didDeleteAtSection:kind:)]){
                [setionView listView:self didDeleteAtSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:didDeleteSectionView:forSection:kind:)]){
                [delegate listView:self didDeleteSectionView:view forSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
    }
}
- (void)_notifyVisiableAttributeChangeWithOld:(NSArray<MKUIListViewAttribute *> *)oldVisiableAttributes newVisiableAttributes:(NSArray<MKUIListViewAttribute *> *)newVisiableAttributes{
    NSArray<UIView *> *oldVisiableViews = [oldVisiableAttributes mk_map:^id _Nullable(MKUIListViewAttribute * _Nonnull obj) {
        return obj.modelView;
    }];
    NSDictionary *oldVisisableViewMap = [oldVisiableAttributes mk_mapDictionary:^NSDictionary * _Nullable(MKUIListViewAttribute * _Nonnull obj) {
        return @{obj.modelView.mk_objectAddress:obj};
    }];
    
    NSArray<UIView *> *newVisiableViews = [newVisiableAttributes mk_map:^id _Nullable(MKUIListViewAttribute * _Nonnull obj) {
        return obj.modelView;
    }];
    NSDictionary *newVisisableViewMap = [newVisiableAttributes mk_mapDictionary:^NSDictionary * _Nullable(MKUIListViewAttribute * _Nonnull obj) {
        return @{obj.modelView.mk_objectAddress:obj};
    }];
    
    NSArray<UIView *> *addVisiableViews = [newVisiableViews mk_removeObjectsInArray:oldVisiableViews];
    NSArray<UIView *> *deleteVisiableViews = [oldVisiableViews mk_removeObjectsInArray:newVisiableViews];
    for (UIView *view in addVisiableViews) {
        MKUIListViewAttribute *attr = newVisisableViewMap[view.mk_objectAddress];
        if(attr){
            [self _notifyAttributeViewWillDisplay:attr];
        }
    }
    for (UIView *view in deleteVisiableViews) {
        MKUIListViewAttribute *attr = oldVisisableViewMap[view.mk_objectAddress];
        if(attr){
            [self _notifyAttributeViewDidEndDisplaying:attr];
        }
    }
}
- (void)_notifyAttributeViewDidAdd:(MKUIListViewAttribute *)attr{
    if(!attr){
        return;
    }
    if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        UIView *view = cellAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListCellViewProtocol)]){
            UIView<MKUIListCellViewProtocol> *cell = (UIView<MKUIListCellViewProtocol> *)view;
            if([cell respondsToSelector:@selector(listView:didAddAtIndexPath:)]){
                [cell listView:self didAddAtIndexPath:cellAttr.indexPath];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:didAddCell:forItemAtIndexPath:)]){
                [delegate listView:self didAddCell:view forItemAtIndexPath:cellAttr.indexPath];
            }
        }
    }else if([attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        MKUIListViewSectionViewAttribute *sectionAttr = (MKUIListViewSectionViewAttribute *)attr;
        UIView *view = sectionAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListSectionViewProtocol)]){
            UIView<MKUIListSectionViewProtocol> *setionView = (UIView<MKUIListSectionViewProtocol> *)view;
            if([setionView respondsToSelector:@selector(listView:didAddAtSection:kind:)]){
                [setionView listView:self didAddAtSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:didAddSectionView:forSection:kind:)]){
                [delegate listView:self didAddSectionView:view forSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
    }
}
- (void)_notifyAttributeViewWillDisplay:(MKUIListViewAttribute *)attr{
    if(!attr){
        return;
    }
    if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        UIView *view = cellAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListCellViewProtocol)]){
            UIView<MKUIListCellViewProtocol> *cell = (UIView<MKUIListCellViewProtocol> *)view;
            if([cell respondsToSelector:@selector(listView:willDisplayAtIndexPath:)]){
                [cell listView:self willDisplayAtIndexPath:cellAttr.indexPath];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:willDisplayCell:forItemAtIndexPath:)]){
                [delegate listView:self willDisplayCell:view forItemAtIndexPath:cellAttr.indexPath];
            }
        }
    }else if([attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        MKUIListViewSectionViewAttribute *sectionAttr = (MKUIListViewSectionViewAttribute *)attr;
        UIView *view = sectionAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListSectionViewProtocol)]){
            UIView<MKUIListSectionViewProtocol> *setionView = (UIView<MKUIListSectionViewProtocol> *)view;
            if([setionView respondsToSelector:@selector(listView:willDisplayAtSection:kind:)]){
                [setionView listView:self willDisplayAtSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:willDisplaySectionView:forSection:kind:)]){
                [delegate listView:self willDisplaySectionView:view forSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
    }
}
- (void)_notifyAttributeViewDidEndDisplaying:(MKUIListViewAttribute *)attr{
    if(!attr){
        return;
    }
    if([attr isKindOfClass:MKUIListViewCellAttribute.class]){
        MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
        UIView *view = cellAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListCellViewProtocol)]){
            UIView<MKUIListCellViewProtocol> *cell = (UIView<MKUIListCellViewProtocol> *)view;
            if([cell respondsToSelector:@selector(listView:didEndDisplayingAtIndexPath:)]){
                [cell listView:self didEndDisplayingAtIndexPath:cellAttr.indexPath];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:didEndDisplayingCell:forItemAtIndexPath:)]){
                [delegate listView:self didEndDisplayingCell:view forItemAtIndexPath:cellAttr.indexPath];
            }
        }
    }else if([attr isKindOfClass:MKUIListViewSectionViewAttribute.class]){
        MKUIListViewSectionViewAttribute *sectionAttr = (MKUIListViewSectionViewAttribute *)attr;
        UIView *view = sectionAttr.modelView;
        if([view conformsToProtocol:@protocol(MKUIListSectionViewProtocol)]){
            UIView<MKUIListSectionViewProtocol> *setionView = (UIView<MKUIListSectionViewProtocol> *)view;
            if([setionView respondsToSelector:@selector(listView:didEndDisplayingAtSection:kind:)]){
                [setionView listView:self didEndDisplayingAtSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
        id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
        if(view && delegate){
            if([delegate respondsToSelector:@selector(listView:didEndDisplayingSectionView:forSection:kind:)]){
                [delegate listView:self didEndDisplayingSectionView:view forSection:sectionAttr.sectionIndex kind:sectionAttr.kind];
            }
        }
    }
}
#pragma mark - private-perform operation
- (CGFloat)_alphaWithPerformOperation:(MKUIListViewPerformOperation *)performOperation{
    CGFloat alpha = 1;
    switch (performOperation.animation) {
        case MKUIListViewItemAnimationFade:
            alpha = 0;
            break;
        case MKUIListViewItemAnimationAutomatic:
            alpha = 0;
        default:
            break;
    }
    return alpha;
}
- (CGAffineTransform)_transformWithPerformOperation:(MKUIListViewPerformOperation *)performOperation{
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    CGRect frame = performOperation.attribute.frame;
    CGAffineTransform m = CGAffineTransformIdentity;
    switch (performOperation.animation) {
        case MKUIListViewItemAnimationFade:
            break;
        case MKUIListViewItemAnimationRight:
            m = MKCGAffineTransformMakeTranslation(X, MKCGRectGetLength(frame, X));
            break;
        case MKUIListViewItemAnimationLeft:
        case MKUIListViewItemAnimationAutomatic:
            m = MKCGAffineTransformMakeTranslation(X, -MKCGRectGetLength(frame, X));
            break;
        case MKUIListViewItemAnimationTop:
            m = MKCGAffineTransformMakeTranslation(Y, -MKCGRectGetLength(frame, Y));
            break;
        case MKUIListViewItemAnimationBottom:
            m = MKCGAffineTransformMakeTranslation(Y, MKCGRectGetLength(frame, Y));
            break;
        case MKUIListViewItemAnimationNone:
            break;
        default:
            break;
    }
    return m;
}
- (void)_willPerformOperation:(MKUIListViewPerformOperation *)performOperation{
    MKUIListViewAttribute *attr = performOperation.attribute;
    UIView *view = attr.attributeView;
    if(!view){
        return;
    }
    switch (performOperation.type) {
        case MKUIListViewPerformTypeRemove:{
            CGFloat alpha = 1;
            CGAffineTransform m = CGAffineTransformIdentity;
            view.alpha = alpha;
            view.transform = m;
        }
            break;
        case MKUIListViewPerformTypeAdd:{
            view.mk_frameSafety = attr.frame;
            CGFloat alpha = [self _alphaWithPerformOperation:performOperation];
            CGAffineTransform m = [self _transformWithPerformOperation:performOperation];
            view.alpha = alpha;
            view.transform = m;
        }
            break;
        case MKUIListViewPerformTypeUpdate:
        case MKUIListViewPerformTypeReload:{
        }
        default:
            break;
    }
}
- (void)_performingOperation:(MKUIListViewPerformOperation *)performOperation{
    UIView *view = performOperation.attribute.attributeView;
    switch (performOperation.type) {
        case MKUIListViewPerformTypeAdd:
        {
            [performOperation.attribute applyAttribute];
            view.alpha = 1;
            view.transform = CGAffineTransformIdentity;
            [performOperation.attribute refreshAttribute];
        }
            break;
        case MKUIListViewPerformTypeRemove:
        {
            CGFloat alpha = [self _alphaWithPerformOperation:performOperation];
            CGAffineTransform m = [self _transformWithPerformOperation:performOperation];
            view.alpha = alpha;
            view.transform = m;
        }
            break;
        case MKUIListViewPerformTypeUpdate:
        {
            [performOperation.attribute applyAttribute];
        }
            break;
        case MKUIListViewPerformTypeReload:
        {
            [performOperation.attribute applyAttribute];
            [performOperation.attribute refreshAttribute];
        }
            break;
        default:
            break;
    }
}
- (void)_didEndPerformOperation:(MKUIListViewPerformOperation *)performOperation{
    UIView *view = performOperation.attribute.attributeView;
    switch (performOperation.type) {
        case MKUIListViewPerformTypeAdd:
        {
            [performOperation.attribute applyAttribute];
            view.alpha = 1;
            view.transform = CGAffineTransformIdentity;
            [performOperation.attribute refreshAttribute];
        }
            break;
        case MKUIListViewPerformTypeRemove:
        {
            [view removeFromSuperview];
        }
            break;
        case MKUIListViewPerformTypeUpdate:
            [performOperation.attribute applyAttribute];
            break;
        case MKUIListViewPerformTypeReload:
            [performOperation.attribute applyAttribute];
            [performOperation.attribute refreshAttribute];
            break;
        default:
            break;
    }
}
#pragma mark - separator
- (void)setSeparatorStyle:(MKUIListViewCellSeparatorStyle)separatorStyle{
    if(_separatorStyle==separatorStyle)return;
    _separatorStyle = separatorStyle;
    [self reloadData];
}
- (void)setSeparatorColor:(UIColor *)separatorColor{
    if(_separatorColor==separatorColor||[_separatorColor isEqual:separatorColor])return;
    _separatorColor = separatorColor;
    for(int i=0;i<self.numberOfSections;i++){
        [self _updateSeparatorColorForSection:i];
    }
}
- (void)setSeparatorBackgroundColor:(UIColor *)separatorBackgroundColor{
    if(_separatorBackgroundColor==separatorBackgroundColor||[_separatorBackgroundColor isEqual:separatorBackgroundColor])return;
    _separatorBackgroundColor = separatorBackgroundColor;
    for(int i=0;i<self.numberOfSections;i++){
        [self _updateSeparatorColorForSection:i];
    }
}
- (void)setSeparatorInsets:(UIEdgeInsets)separatorInsets{
    if(UIEdgeInsetsEqualToEdgeInsets(_separatorInsets, separatorInsets))return;
    _separatorInsets = separatorInsets;
    [self reloadData];
}
- (void)setSeparatorSize:(CGFloat)separatorSize{
    if(_separatorSize==separatorSize)return;
    _separatorSize = separatorSize;
    [self reloadData];
}
- (void)setSeparatorViewClass:(Class)separatorViewClass{
    if(_separatorViewClass==separatorViewClass)return;
    _separatorViewClass = separatorViewClass;
    [self reloadData];
}
- (void)setCellInteritemSpacing:(CGFloat)cellInteritemSpacing{
    if(_cellInteritemSpacing==cellInteritemSpacing)return;
    _cellInteritemSpacing = cellInteritemSpacing;
    [self _updateAllAttributesFrame];
}
- (void)setSectionInteritemSpacing:(CGFloat)sectionInteritemSpacing{
    if(_sectionInteritemSpacing==sectionInteritemSpacing)return;
    _sectionInteritemSpacing = sectionInteritemSpacing;
    [self _updateAllAttributesFrame];
}
- (void)_updateAllAttributesFrame{
    [self _beforeUpdateAttributes];
    for (MKUIListViewAttribute *attr in self.attributes) {
        [self _addPerformOperation:[[MKUIListViewPerformOperation alloc] initWithAttribute:attr type:(MKUIListViewPerformTypeUpdate) animation:MKUIListViewItemAnimationNone]];
    }
    //upload分组背景
    [self _reloadSectionGroupBackgroundAttributes:self.sectionGroupBacgroundAttributes withAnimation:(MKUIListViewItemAnimationNone)];
    
    [self _afterUpdateAttributes];
}
#pragma mark - InsetGrouped
- (BOOL)hasInsetGrouped{
    return self.style==MKUIListViewStyleInsetGrouped;
}
- (void)setStyle:(MKUIListViewStyle)style{
    if(_style==style)return;
    _style = style;
    [self reloadData];
}
- (void)setGroupBackgroundColor:(UIColor *)groupBackgroundColor{
    if(_groupBackgroundColor==groupBackgroundColor || [_groupBackgroundColor isEqual:groupBackgroundColor]) return;
    _groupBackgroundColor = groupBackgroundColor;
    
    for(int i=0;i<self.numberOfSections;i++){
        [self _updateGroupBackgroundColorForSection:i];
    }
}
- (void)_updateGroupBackgroundColorForSection:(NSInteger)sectionIndex{
    UIColor *color = [self groupBackgroundColorForSection:sectionIndex];
    MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = [self _sectionGroupBackgroundAttributesAtSection:sectionIndex];
    sectionBgAttr.groupBackgroundColor = color;
    [sectionBgAttr applyAttribute];
}
- (void)setGroupBackgroundViewClass:(Class)groupBackgroundViewClass{
    if(_groupBackgroundViewClass==groupBackgroundViewClass)return;
    _groupBackgroundViewClass = groupBackgroundViewClass;
    
    for(int i=0;i<self.numberOfSections;i++){
        [self _updateGroupBackgroundViewClassForSection:i];
    }
}
- (void)_updateGroupBackgroundViewClassForSection:(NSInteger)sectionIndex{
    Class groupBackgroundViewClass = [self groupBackgroundViewClassForSetion:sectionIndex];
    
    MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = [self _sectionGroupBackgroundAttributesAtSection:sectionIndex];
    sectionBgAttr.groupBackgroundViewClass = groupBackgroundViewClass;
    [sectionBgAttr applyAttribute];
}
- (void)setGroupInsets:(UIEdgeInsets)groupInsets{
    if(UIEdgeInsetsEqualToEdgeInsets(_groupInsets, groupInsets)) return;
    _groupInsets = groupInsets;
    [self reloadData];
}
- (void)setGroupCornerRadius:(CGFloat)groupCornerRadius{
    if(_groupCornerRadius == groupCornerRadius) return;
    _groupCornerRadius = groupCornerRadius;
    
    for(int i=0;i<self.numberOfSections;i++){
        [self _updateGroupCornerRadiusForSection:i];
    }
}
- (void)setGroupInnerInsets:(UIEdgeInsets)groupInnerInsets{
    if(UIEdgeInsetsEqualToEdgeInsets(_groupInnerInsets, groupInnerInsets)) return;
    _groupInnerInsets = groupInnerInsets;
    [self reloadData];
}
- (void)_updateGroupCornerRadiusForSection:(NSInteger)sectionIndex{
    CGFloat groupCornerRadius = [self groupCornerRadiusForSection:sectionIndex];
    
    MKUIListViewSectionGroupBackgroundViewAttribute *sectionBgAttr = [self _sectionGroupBackgroundAttributesAtSection:sectionIndex];
    sectionBgAttr.groupCornerRadius = groupCornerRadius;
    [sectionBgAttr applyAttribute];
    
    NSArray<MKUIListViewCellAttribute *> *cellAttrs = [self _cellAttributesInSection:sectionIndex];
    for(MKUIListViewCellAttribute *cellAttr in cellAttrs){
        cellAttr.groupCornerRadius = groupCornerRadius;
        [sectionBgAttr applyAttribute];
    }
}
- (BOOL)_hasGroupBackgroundViweForSection:(NSInteger)section{
    return YES;
}
#pragma mark - 定制各分组的属性
- (nullable Class)groupBackgroundViewClassForSetion:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:groupBackgroundViewClassForSetion:)]){
        return [delegate listView:self groupBackgroundViewClassForSetion:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.groupBackgroundViewClass!=nil){
        return sectionModel.groupBackgroundViewClass;
    }
    return self.groupBackgroundViewClass;
}
- (void)setGroupBackgroundViewClass:(Class _Nullable)groupBackgroundViewClass forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    Class oldValue = [self groupBackgroundViewClassForSetion:section];
    if(oldValue==groupBackgroundViewClass)return;
    sectionModel.groupBackgroundViewClass = groupBackgroundViewClass;
    [self _updateGroupBackgroundViewClassForSection:section];
}
- (UIColor *)groupBackgroundColorForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:groupBackgroundColorForSection:)]){
        return [delegate listView:self groupBackgroundColorForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.groupBackgroundColor){
        return sectionModel.groupBackgroundColor;
    }
    return self.groupBackgroundColor;
    
}
- (void)setGroupBackgroundColor:(nullable UIColor *)color forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    UIColor *oldValue = [self groupBackgroundColorForSection:section];
    if(oldValue==color||[oldValue isEqual:color])return;
    sectionModel.groupBackgroundColor = color;
    [self _updateGroupBackgroundColorForSection:section];
}
- (UIEdgeInsets)groupInsetsForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:groupInsetsForSection:)]){
        return [delegate listView:self groupInsetsForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.groupInsetsValue){
        return sectionModel.groupInsetsValue.UIEdgeInsetsValue;
    }
    return self.groupInsets;
}
- (UIEdgeInsets)groupInsetsWithSafeAreaInsetsForSection:(NSInteger)section{
    if(self.style==MKUIListViewStylePlain) return UIEdgeInsetsZero;
    UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        safeAreaInsets = self.safeAreaInsets;
    }
    MKCGAxis Y = self.scrollAxis;
    MKCGAxis X = MKCGAxisReverse(Y);
    UIEdgeInsets groupInsets = [self groupInsetsForSection:section];
    MKUIEdgeInsetsAddEdge(&groupInsets, X, MKUIEdgeInsetsMin, MKUIEdgeInsetsGetEdge(safeAreaInsets, X, MKUIEdgeInsetsMin));
    MKUIEdgeInsetsAddEdge(&groupInsets, X, MKUIEdgeInsetsMax, MKUIEdgeInsetsGetEdge(safeAreaInsets, X, MKUIEdgeInsetsMax));
    return groupInsets;
}
- (void)setGroupInsets:(UIEdgeInsets)insets forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    NSValue *oldValue = sectionModel.groupInsetsValue;
    NSValue *newValue = [NSValue valueWithUIEdgeInsets:insets];
    if(oldValue==newValue||[oldValue isEqualToValue:newValue])return;
    sectionModel.groupInsetsValue = newValue;
    [self reloadSection:section];
}
- (CGFloat)groupCornerRadiusForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:groupCornerRadiusForSection:)]){
        return [delegate listView:self groupCornerRadiusForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.groupCornerRadiusNumber){
        return sectionModel.groupCornerRadiusNumber.floatValue;
    }
    return self.groupCornerRadius;
}
- (void)setGroupCornerRadius:(CGFloat)radius forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    NSNumber *oldValue = sectionModel.groupCornerRadiusNumber;
    NSNumber *newValue = @(radius);
    if(oldValue==newValue||[oldValue isEqualToNumber:newValue])return;
    sectionModel.groupCornerRadiusNumber = newValue;
    [self _updateGroupCornerRadiusForSection:section];
}
- (UIEdgeInsets)groupInnerInsetsForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:groupInnerInsetsForSection:)]){
        return [delegate listView:self groupInnerInsetsForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.groupInnerInsetsValue){
        return sectionModel.groupInnerInsetsValue.UIEdgeInsetsValue;
    }
    return self.groupInnerInsets;
}
- (void)setGroupInnerInsets:(UIEdgeInsets)insets forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    NSValue *oldValue = sectionModel.groupInnerInsetsValue;
    NSValue *newValue = [NSValue valueWithUIEdgeInsets:insets];
    if(oldValue==newValue||[oldValue isEqualToValue:newValue])return;
    sectionModel.groupInnerInsetsValue = newValue;
    [self reloadSection:section];
}
- (CGFloat)cellInteritemSpacingForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:cellInteritemSpacingForSection:)]){
        return [delegate listView:self cellInteritemSpacingForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.cellInteritemSpacingNumber){
        return sectionModel.cellInteritemSpacingNumber.floatValue;
    }
    return self.cellInteritemSpacing;
}
- (void)setCellInteritemSpacing:(CGFloat)spacing forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    NSNumber *oldValue = sectionModel.cellInteritemSpacingNumber;
    NSNumber *newValue = @(spacing);
    if(oldValue==newValue||[oldValue isEqualToNumber:newValue])return;
    sectionModel.cellInteritemSpacingNumber = newValue;
    [self reloadSection:section];
}
#pragma mark - 定制各分组的分隔线属性
- (MKUIListViewCellSeparatorStyle)separatorStyleForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:separatorStyleForSection:)]){
        return [delegate listView:self separatorStyleForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.separatorStyleNumber){
        return (MKUIListViewCellSeparatorStyle)sectionModel.separatorStyleNumber.integerValue;
    }
    return self.separatorStyle;
}
- (void)setSeparatorStyle:(MKUIListViewCellSeparatorStyle)style forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    NSNumber *oldValue = sectionModel.separatorStyleNumber;
    NSNumber *newValue = @(style);
    if(oldValue==newValue||[oldValue isEqual:newValue])return;
    sectionModel.separatorStyleNumber = newValue;
    [self reloadSection:section];
}
- (nullable UIColor *)separatorColorForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:separatorColorForSection:)]){
        return [delegate listView:self separatorColorForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.separatorColor){
        return sectionModel.separatorColor;
    }
    return self.separatorColor;
}
- (void)setSeparatorColor:(nullable UIColor *)color forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    UIColor *oldValue = [self separatorColorForSection:section];
    if(oldValue==color||[oldValue isEqual:color])return;
    sectionModel.separatorColor = color;
    [self _updateSeparatorColorForSection:section];
}
- (void)_updateSeparatorColorForSection:(NSInteger)section{
    UIColor *separatorColor = [self separatorColorForSection:section];
    NSArray<MKUIListViewCellAttribute *> *cellAttrs = [self _cellAttributesInSection:section];
    for(MKUIListViewCellAttribute *cellAttr in cellAttrs){
        cellAttr.separatorColor = separatorColor;
        [cellAttr applyAttribute];
    }
}
- (nullable UIColor *)separatorBackgroundColorForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:separatorBackgroundColorForSection:)]){
        return [delegate listView:self separatorBackgroundColorForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.separatorBackgroundColor){
        return sectionModel.separatorBackgroundColor;
    }
    return self.separatorBackgroundColor;
}
- (void)setSeparatorBackgroundColor:(nullable UIColor *)color forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    UIColor *oldValue = [self separatorBackgroundColorForSection:section];
    if(oldValue==color||[oldValue isEqual:color])return;
    sectionModel.separatorBackgroundColor = color;
    [self _updateSeparatorBackgroundColorForSection:section];
}
- (void)_updateSeparatorBackgroundColorForSection:(NSInteger)section{
    UIColor *separatorBackgroundColor = [self separatorBackgroundColorForSection:section];
    NSArray<MKUIListViewCellAttribute *> *cellAttrs = [self _cellAttributesInSection:section];
    for(MKUIListViewCellAttribute *cellAttr in cellAttrs){
        cellAttr.separatorBackgroundColor = separatorBackgroundColor;
        [cellAttr applyAttribute];
    }
}
- (CGFloat)separatorSizeForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:separatorSizeForSection:)]){
        return [delegate listView:self separatorSizeForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.separatorSizeNumber){
        return sectionModel.separatorSizeNumber.floatValue;
    }
    return self.separatorSize;
}
- (void)setSeparatorSize:(CGFloat)size forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    NSInteger oldValue = [self separatorSizeForSection:section];
    if(oldValue==size)return;
    sectionModel.separatorSizeNumber = @(size);
    [self reloadSection:section];
}
- (UIEdgeInsets)separatorInsetsForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:separatorInsetsForSection:)]){
        return [delegate listView:self separatorInsetsForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.separatorInsetsValue){
        return sectionModel.separatorInsetsValue.UIEdgeInsetsValue;
    }
    return self.separatorInsets;
}
- (void)setSeparatorInsets:(UIEdgeInsets)insets forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    UIEdgeInsets oldValue = [self separatorInsetsForSection:section];
    if(UIEdgeInsetsEqualToEdgeInsets(oldValue, insets))return;
    sectionModel.separatorInsetsValue = [NSValue valueWithUIEdgeInsets:insets];
    [self reloadSection:section];
}
- (nullable Class)separatorViewClassForSection:(NSInteger)section{
    id<MKUIListViewDelegate> delegate = [self _listViewDelegate];
    if([delegate respondsToSelector:@selector(listView:separatorViewClassForSection:)]){
        return [delegate listView:self separatorViewClassForSection:section];
    }
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(sectionModel.separatorViewClass){
        return sectionModel.separatorViewClass;
    }
    return self.separatorViewClass;
}
- (void)setSeparatorViewClass:(Class)aClass forSection:(NSInteger)section{
    MKUIListViewSectionAttributeModel *sectionModel = [self _sectionAttributeModelAtIndex:section];
    if(!sectionModel)return;
    Class oldValue = [self separatorViewClassForSection:section];
    if(oldValue==aClass)return;
    sectionModel.separatorViewClass = aClass;
    [self reloadSection:section];
}
- (void)__updateGroupAttributesWithBeginAttribute:(MKUIListViewAttribute *)attr animation:(MKUIListViewItemAnimation)animation{
    if(!attr || ![self hasInsetGrouped])return;
    if(![attr isKindOfClass:MKUIListViewCellAttribute.class]){
        return;
    }
    MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)attr;
    MKUIListViewCellAttribute *currentCellAttr = [self _cellAttributeAtIndexPath:[NSIndexPath indexPathForItem:cellAttr.itemIndex inSection:cellAttr.sectionIndex]];
    MKUIListViewCellAttribute *preCellAttr = [self _cellAttributeAtIndexPath:[NSIndexPath indexPathForItem:cellAttr.itemIndex-1 inSection:cellAttr.sectionIndex]];
    MKUIListViewCellAttribute *nextCellAttr = [self _cellAttributeAtIndexPath:[NSIndexPath indexPathForItem:cellAttr.itemIndex+1 inSection:cellAttr.sectionIndex]];
    
    NSMutableArray<MKUIListViewAttribute *> *attrList = [[NSMutableArray alloc] init];
    if(cellAttr && ![attrList containsObject:cellAttr]){
        [attrList addObject:cellAttr];
    }
    if(preCellAttr && ![attrList containsObject:preCellAttr]){
        [attrList addObject:preCellAttr];
    }
    if(currentCellAttr && ![attrList containsObject:currentCellAttr]){
        [attrList addObject:currentCellAttr];
    }
    if(nextCellAttr && ![attrList containsObject:nextCellAttr]){
        [attrList addObject:nextCellAttr];
    }
    for(MKUIListViewCellAttribute *cellAttr in attrList){
        [cellAttr configAttributeWithListView:self];
        [cellAttr applyAttribute];
    }
}
#pragma mark - touch event
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{
//    NSLog(@"touchesBegan:%@",self);
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    NSIndexPath *cellIndexPath = [self indexPathForItemAtPoint:p];
    self.touchingCellIndexPath = cellIndexPath;
    if(cellIndexPath){
        UIView *cell = [self cellForItemAtIndexPath:cellIndexPath];
        if([cell conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [cell respondsToSelector:@selector(listView:willSelectAtIndexPath:)]){
            [(id<MKUIListCellViewProtocol>)cell listView:self willSelectAtIndexPath:cellIndexPath];
        }
        //
        if([self.delegate conformsToProtocol:@protocol(MKUIListViewDelegate)] && [self.delegate respondsToSelector:@selector(listView:willSelectCell:forItemAtIndexPath:)]){
            [(id<MKUIListViewDelegate>)self.delegate listView:self willSelectCell:cell forItemAtIndexPath:cellIndexPath];
        }
//        NSLog(@"willSelectCell:%@",cellIndexPath);
    }
    [super touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{
//    NSLog(@"touchesMoved:%@",self);
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    NSIndexPath *cellIndexPath = [self indexPathForItemAtPoint:p];
    
    if(self.touchingCellIndexPath && ![self.touchingCellIndexPath isEqual:cellIndexPath]){//取消旧的选中
        NSIndexPath *cellIndexPath = self.touchingCellIndexPath;
        UIView *cell = [self cellForItemAtIndexPath:cellIndexPath];
        if([cell conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [cell respondsToSelector:@selector(listView:cancelSelectAtIndexPath:)]){
            [(id<MKUIListCellViewProtocol>)cell listView:self cancelSelectAtIndexPath:cellIndexPath];
        }
        //
        if([self.delegate conformsToProtocol:@protocol(MKUIListViewDelegate)] && [self.delegate respondsToSelector:@selector(listView:cancelSelectCell:forItemAtIndexPath:)]){
            [(id<MKUIListViewDelegate>)self.delegate listView:self cancelSelectCell:cell forItemAtIndexPath:cellIndexPath];
        }
//        NSLog(@"cancelSelectCell:%@",cellIndexPath);
    }
    if(cellIndexPath && ![cellIndexPath isEqual:self.touchingCellIndexPath]){
        UIView *cell = [self cellForItemAtIndexPath:cellIndexPath];
        if([cell conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [cell respondsToSelector:@selector(listView:willSelectAtIndexPath:)]){
            [(id<MKUIListCellViewProtocol>)cell listView:self willSelectAtIndexPath:cellIndexPath];
        }
        //
        if([self.delegate conformsToProtocol:@protocol(MKUIListViewDelegate)] && [self.delegate respondsToSelector:@selector(listView:willSelectCell:forItemAtIndexPath:)]){
            [(id<MKUIListViewDelegate>)self.delegate listView:self willSelectCell:cell forItemAtIndexPath:cellIndexPath];
        }
//        NSLog(@"willSelectCell:%@",cellIndexPath);
    }
    self.touchingCellIndexPath = cellIndexPath;
    [super touchesMoved:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{
//    NSLog(@"touchesCancelled:%@",self);
    if(self.touchingCellIndexPath){//取消旧的选中
        NSIndexPath *cellIndexPath = self.touchingCellIndexPath;
        UIView *cell = [self cellForItemAtIndexPath:cellIndexPath];
        if([cell conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [cell respondsToSelector:@selector(listView:cancelSelectAtIndexPath:)]){
            [(id<MKUIListCellViewProtocol>)cell listView:self cancelSelectAtIndexPath:cellIndexPath];
        }
        //
        if([self.delegate conformsToProtocol:@protocol(MKUIListViewDelegate)] && [self.delegate respondsToSelector:@selector(listView:cancelSelectCell:forItemAtIndexPath:)]){
            [(id<MKUIListViewDelegate>)self.delegate listView:self cancelSelectCell:cell forItemAtIndexPath:cellIndexPath];
        }
//        NSLog(@"cancelSelectCell:%@",cellIndexPath);
    }
    self.touchingCellIndexPath = nil;
    [super touchesCancelled:touches withEvent:event];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//    NSLog(@"touchesEnded:%@",self);
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    NSIndexPath *cellIndexPath = [self indexPathForItemAtPoint:p];
    
    if(self.touchingCellIndexPath && ![self.touchingCellIndexPath isEqual:cellIndexPath]){//取消旧的选中
        NSIndexPath *cellIndexPath = self.touchingCellIndexPath;
        UIView *cell = [self cellForItemAtIndexPath:cellIndexPath];
        if([cell conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [cell respondsToSelector:@selector(listView:cancelSelectAtIndexPath:)]){
            [(id<MKUIListCellViewProtocol>)cell listView:self cancelSelectAtIndexPath:cellIndexPath];
        }
        //
        if([self.delegate conformsToProtocol:@protocol(MKUIListViewDelegate)] && [self.delegate respondsToSelector:@selector(listView:cancelSelectCell:forItemAtIndexPath:)]){
            [(id<MKUIListViewDelegate>)self.delegate listView:self cancelSelectCell:cell forItemAtIndexPath:cellIndexPath];
        }
//        NSLog(@"cancelSelectCell:%@",cellIndexPath);
    }
    
    if(cellIndexPath){
        UIView *cell = [self cellForItemAtIndexPath:cellIndexPath];
        if([cell conformsToProtocol:@protocol(MKUIListCellViewProtocol)] && [cell respondsToSelector:@selector(listView:didSelectAtIndexPath:)]){
            [(id<MKUIListCellViewProtocol>)cell listView:self didSelectAtIndexPath:cellIndexPath];
        }
        //
        if([self.delegate conformsToProtocol:@protocol(MKUIListViewDelegate)] && [self.delegate respondsToSelector:@selector(listView:didSelectCell:forItemAtIndexPath:)]){
            [(id<MKUIListViewDelegate>)self.delegate listView:self didSelectCell:cell forItemAtIndexPath:cellIndexPath];
        }
//        NSLog(@"didSelectCell:%@",cellIndexPath);
    }
    self.touchingCellIndexPath = nil;
    [super touchesEnded:touches withEvent:event];
}
@end

@interface MKUIListViewSubViewBase()
@property(nonatomic,strong) UIView *contentView;
@end
@implementation MKUIListViewSubViewBase
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.contentView = [[UIView alloc] initWithFrame:frame];
        [self addSubview:self.contentView];
    }
    return self;
}
- (void)layoutSubviews{
    [super layoutSubviews];
    [self layoutContentView];
}
- (void)layoutContentView{
    CGRect bounds = self.bounds;
    UIEdgeInsets insets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        insets = self.safeAreaInsets;
    }
    self.contentView.frame = UIEdgeInsetsInsetRect(bounds, insets);
}
- (CGSize)listView:(MKUIListView *)listView sizeThatFits:(CGSize)size atIndexPath:(NSIndexPath *)indexPath{
    UIEdgeInsets insets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        insets = self.safeAreaInsets;
    }
    MKCGSizeAddLength(&size, MKCGAxisX, -MKUIEdgeInsetsGetEdgeSum(insets, MKCGAxisX));
    MKCGSizeAddLength(&size, MKCGAxisY, -MKUIEdgeInsetsGetEdgeSum(insets, MKCGAxisY));
    return [self sizeThatFits:size];
}
@end

@interface MKUIListPinHeadViewBase()
@property(nonatomic,assign) MKUIListViewScrollDirection scrollDirection;
@property(nonatomic,readonly) MKCGAxis scrollAxis;
@property(nonatomic,assign) CGFloat originZPosition;
@end
@implementation MKUIListPinHeadViewBase
- (id)initWithFrame:(CGRect)frame{
    if (self=[super initWithFrame:frame]) {
        self.enablePinning = YES;
    }
    return self;
}
- (MKCGAxis)scrollAxis{
    MKCGAxis X = self.scrollDirection==UICollectionViewScrollDirectionHorizontal?MKCGAxisX:MKCGAxisY;
    return X;
}
- (void)setEnablePinning:(BOOL)enablePinning{
    if(_enablePinning!=enablePinning){
        _enablePinning = enablePinning;
        [self _onContentOffsetChange];
    }
}
- (CGFloat)minSizeOfPinning{
    MKCGAxis Y = [self scrollAxis];
    return MKCGRectGetLength(self.bounds, Y);
}
- (void)listViewDidChangeContentOffset:(MKUIListView *)listView{
    MKCGAxis Y = [self scrollAxis];
    MKUIListViewAttributeContainerView *containerView = [listView containerViewForView:self];
    
    //调整transform
    CGPoint offset = listView.contentOffset;
    UIEdgeInsets contentInsets = listView.mk_adjustedContentInset;
    CGRect f1 = [containerView.superview convertRect:containerView.mk_frameSafety toView:listView];
    CGFloat maxChangeHeight = MKCGRectGetLength(self.bounds, Y)-self.minSizeOfPinning;
//    CGFloat dHeight = 0;
    CGAffineTransform m = CGAffineTransformIdentity;
    //
    if(self.enablePinning){
//        CGFloat progress = 0;
        CGFloat y0 = MKCGRectGetMin(f1, Y);
        CGFloat y1 = MKCGPointGetValue(offset, Y)+MKUIEdgeInsetsGetEdge(contentInsets, Y, MKUIEdgeInsetsMin);
        if(y1>y0){
            CGFloat dy = y1-y0;
            if(dy<maxChangeHeight){
//                progress = dy/maxChangeHeight;
//                dHeight = -dy;
            }else{
//                progress = 1;
//                dHeight = -maxChangeHeight;
                m = MKCGAffineTransformMakeTranslation(Y, dy-maxChangeHeight);
            }
        }
    }
    containerView.transform = m;//让自身pin在listView的顶部
}

#pragma mark - delegate:MKUIListCellViewProtocol,MKUIListSectionViewProtocol
- (void)listView:(MKUIListView *)listView didAddAtIndexPath:(NSIndexPath *)indexPath{
    [self _onDidAddTo:listView];
}
- (void)listView:(MKUIListView *)listView didDeleteAtIndexPath:(nonnull NSIndexPath *)indexPath{
    [self _onDidDeleteFrom:listView];
}
- (void)listView:(MKUIListView *)listView willDisplayAtIndexPath:(nonnull NSIndexPath *)indexPath{
    [self _onWillDisplayTo:listView];
}
- (void)listView:(MKUIListView *)listView didAddAtSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind{
    [self _onDidAddTo:listView];
}
- (void)listView:(MKUIListView *)listView didDeleteAtSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind{
    [self _onDidDeleteFrom:listView];
}
- (void)listView:(MKUIListView *)listView willDisplayAtSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind{
    [self _onWillDisplayTo:listView];
}
- (CGFloat)listView:(MKUIListView *)listView zIndexFor:(CGFloat)zIndex atSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind{
    return [self _calZIndex:zIndex];
}
- (CGFloat)listView:(MKUIListView *)listView zIndexFor:(CGFloat)zIndex atIndexPath:(NSIndexPath *)indexPath{
    return [self _calZIndex:zIndex];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if([keyPath isEqualToString:NSStringFromSelector(@selector(contentOffset))]){
        [self _onContentOffsetChange];
    }
}
#pragma mark - private
- (CGFloat)_calZIndex:(CGFloat)zIndex{
    return self.enablePinning?zIndex+1000000:zIndex;
}
- (void)_onDidAddTo:(MKUIListView *)listView{
    [listView addObserver:self forKeyPath:NSStringFromSelector(@selector(contentOffset)) options:(NSKeyValueObservingOptionNew) context:nil];
}
- (void)_onDidDeleteFrom:(MKUIListView *)listView{
    [listView removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentOffset)) context:nil];
    MKUIListViewAttributeContainerView *containerView = [listView containerViewForView:self];
    containerView.layer.zPosition = self.originZPosition;
}
- (void)_onWillDisplayTo:(MKUIListView *)listView{
    [self _onContentOffsetChange];
}
- (void)_onContentOffsetChange{
    MKUIListView *listView = [self mk_firstSuperViewWithClass:[MKUIListView class]];
    [self listViewDidChangeContentOffset:listView];
}
@end

@interface MKUIListSelectionCellViewBase ()
@property(nonatomic,strong) UIView *systemSelectedBackgroundView;
@end

@implementation MKUIListSelectionCellViewBase
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.enableSelection = YES;
        self.systemSelectedBackgroundView = [[UIView alloc] init];
        self.systemSelectedBackgroundView.hidden = YES;
        self.systemSelectedBackgroundView.alpha = 0;
        [self addSubview:self.systemSelectedBackgroundView];
        [self sendSubviewToBack:self.systemSelectedBackgroundView];
        self.selectedBackgroundColor = UIColor.mk_listViewCellSelectedColor;
    }
    return self;
}
- (void)layoutSubviews{
    [super layoutSubviews];
    self.systemSelectedBackgroundView.frame = self.bounds;
    self.selectedBackgroundView.frame = self.bounds;
}
- (void)setSelectedBackgroundView:(UIView *)selectedBackgroundView{
    if(_selectedBackgroundView==selectedBackgroundView)return;
    [_selectedBackgroundView removeFromSuperview];
    _selectedBackgroundView = selectedBackgroundView;
    if(_selectedBackgroundView)[self.systemSelectedBackgroundView addSubview:_selectedBackgroundView];
    [self setNeedsLayout];
}
- (void)setHighlighted:(BOOL)highlighted{
    [self setHighlighted:highlighted animated:NO];
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated{
    if(self.selected) return;
    
    if(animated){
        if(highlighted){
            self.systemSelectedBackgroundView.hidden = NO;
            [UIView animateWithDuration:0.15 animations:^{
                self.systemSelectedBackgroundView.backgroundColor = self.highlightedBackgroundColor?:self.selectedBackgroundColor;
                self.systemSelectedBackgroundView.alpha = 1;
            } completion:^(BOOL finished) {
                self->_highlighted = highlighted;
            }];
        }else{
            [UIView animateWithDuration:0.2 animations:^{
                self.systemSelectedBackgroundView.backgroundColor = nil;
                self.systemSelectedBackgroundView.alpha = 0;
            } completion:^(BOOL finished) {
                self.systemSelectedBackgroundView.hidden = YES;
                self->_highlighted = highlighted;
            }];
        }
    }else{
        self.systemSelectedBackgroundView.backgroundColor = self.highlightedBackgroundColor?:nil;
        self.systemSelectedBackgroundView.alpha = highlighted?1:0;
        self.systemSelectedBackgroundView.hidden = !highlighted;
        _highlighted = highlighted;
    }
}
- (void)setSelected:(BOOL)selected{
    [self setSelected:selected animated:NO];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
    [self setSelected:selected animated:animated completion:nil];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion{
    if(animated){
        if(selected){
            self.systemSelectedBackgroundView.hidden = NO;
            [UIView animateWithDuration:0.25 animations:^{
                self.systemSelectedBackgroundView.backgroundColor = self.selectedBackgroundColor;
                self.systemSelectedBackgroundView.alpha = 1;
            } completion:^(BOOL finished) {
                self->_highlighted = NO;
                self->_selected = selected;
                if(self.whenSelected){
                    self.whenSelected(self, selected);
                }
                [self didSelected:selected];
                if(completion){
                    completion(finished);
                }
            }];
        }else{
            [UIView animateWithDuration:0.25 animations:^{
                self.systemSelectedBackgroundView.backgroundColor = nil;
                self.systemSelectedBackgroundView.alpha = 0;
            } completion:^(BOOL finished) {
                self.systemSelectedBackgroundView.hidden = YES;
                self->_highlighted = NO;
                self->_selected = selected;
                if(self.whenSelected){
                    self.whenSelected(self, selected);
                }
                [self didSelected:selected];
                if(completion){
                    completion(finished);
                }
            }];
        }
    }else{
        self.systemSelectedBackgroundView.backgroundColor = selected?self.selectedBackgroundColor:nil;
        self.systemSelectedBackgroundView.alpha = selected?1:0;
        self.systemSelectedBackgroundView.hidden = !selected;
        _highlighted = NO;
        _selected = selected;
        if(self.whenSelected){
            self.whenSelected(self, selected);
        }
        [self didSelected:selected];
        if(completion){
            completion(YES);
        }
    }
}
- (void)didSelected:(BOOL)selected{
    if(selected){
        [self setSelected:NO animated:YES];
        [self didClick];
        if(self.whenClick){
            self.whenClick(self);
        }
    }
}
- (void)didClick{
    
}
#pragma mark - delegate:MKUIListCellViewProtocol
- (void)listView:(MKUIListView *)listView willSelectAtIndexPath:(NSIndexPath *)indexPath{
    if(!self.enableSelection) return;
    [self setHighlighted:YES animated:YES];
}
- (void)listView:(MKUIListView *)listView cancelSelectAtIndexPath:(NSIndexPath *)indexPath{
    if(!self.enableSelection) return;
    [self setHighlighted:NO animated:YES];
}
- (void)listView:(MKUIListView *)listView didSelectAtIndexPath:(NSIndexPath *)indexPath{
    if(!self.enableSelection) return;
    [self setSelected:YES animated:YES];
}
@end
@implementation MKUIListView(CellSelection)
- (NSIndexPath *)indexPathForSelectedItem{
    return self.indexPathsForVisibleItems.firstObject;
}
- (NSArray<NSIndexPath *> *)indexPathsForSelectedItems{
    return [self.attributes mk_map:^id _Nullable(MKUIListViewAttribute *obj) {
        if([obj isKindOfClass:MKUIListViewCellAttribute.class] && [obj.modelView isKindOfClass:[MKUIListSelectionCellViewBase class]]){
            MKUIListViewCellAttribute *cellAttr = (MKUIListViewCellAttribute *)obj;
            MKUIListSelectionCellViewBase *cell = (MKUIListSelectionCellViewBase *)cellAttr.modelView;
            if(!cell.enableSelection) return nil;
            if(cell.selected){
                return cellAttr.indexPath;
            }
        }
        return nil;
    }];
}
- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(MKUIListViewScrollPosition)scrollPosition{
    UIView *view = [self cellForItemAtIndexPath:indexPath];
    if(!view || ![view isKindOfClass:[MKUIListSelectionCellViewBase class]]) return;
    MKUIListSelectionCellViewBase *cell = (MKUIListSelectionCellViewBase *)view;
    if(!cell.enableSelection) return;
    [cell setSelected:YES animated:animated];
    [self scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated completion:nil];
}
- (void)selectItem:(MKUIListSelectionCellViewBase *)cell animated:(BOOL)animated scrollPosition:(MKUIListViewScrollPosition)scrollPosition{
    if(!cell.enableSelection)return;
    [cell setSelected:YES animated:animated];
    [self scrollToItemAtIndexPath:[self indexPathForCell:cell] atScrollPosition:scrollPosition animated:animated completion:nil];
}
- (void)deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated{
    UIView *view = [self cellForItemAtIndexPath:indexPath];
    if(!view || ![view isKindOfClass:[MKUIListSelectionCellViewBase class]]) return;
    MKUIListSelectionCellViewBase *cell = (MKUIListSelectionCellViewBase *)view;
    if(!cell.enableSelection)return;
    [cell setSelected:NO animated:animated];
}
- (void)deselectItem:(MKUIListSelectionCellViewBase *)cell animated:(BOOL)animated{
    if(!cell.enableSelection)return;
    [cell setSelected:NO animated:animated];
}
- (void)deselectAllItemsWithAnimated:(BOOL)animated{
    for(NSIndexPath *indexPath in [self indexPathsForSelectedItems]){
        [self deselectItemAtIndexPath:indexPath animated:animated];
    }
}

@end

@implementation UIView(MKUIListView)
- (MKUIListView *)mk_listView{
    return [self mk_firstSuperViewWithClass:[MKUIListView class]];
}
- (MKUIListViewAttributeContainerView *)mk_attributeContainerInListView{
    MKUIListView *listView = self.mk_listView;
    return [listView containerViewForView:self];
}
- (void)mk_reloadInListViewWithAnimation:(MKUIListViewItemAnimation)animation{
    [self.mk_listView reloadView:self withAnimation:(animation)];
}
- (void)mk_reloadInListView{
    [self mk_reloadInListViewWithAnimation:(MKUIListViewItemAnimationNone)];
}
- (UIView *)mk_nearestAttributeViewInListView{
    MKUIListViewAttributeContainerView *containerView = [self mk_firstSuperViewWithClass:MKUIListViewAttributeContainerView.class];
    return containerView.attributeView;
}
@end
